package com.xbongbong.paas.service.impl;

import com.alibaba.dingtalk.openapi.helper.Env;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.call.CallCenterService;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.domain.entity.ext.OptionalRangeEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.ModuleTypeEnum;
import com.xbongbong.paas.enums.OptionalRangeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.factory.UserDeptOptionalRangeFactory;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.FilterConditionsPoJo;
import com.xbongbong.paas.field.LimitChooseRangePoJo;
import com.xbongbong.paas.help.CloudCodeHelp;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.alibaba.dingtalk.openapi.helper.RestTemplateHelper;
import com.xbongbong.paas.help.UserInfoHelp;
import com.xbongbong.paas.help.optional.range.UserDeptOptionalRangeHandler;
import com.xbongbong.paas.help.permission.PermissionHelp;
import com.xbongbong.paas.help.team.TeamRedisHelper;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.manager.feign.SyncDataToXbbFeignClient;
import com.xbongbong.paas.model.DeveloperModel;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.model.SearchCustomerCompanyModel;
import com.xbongbong.paas.pojo.AppPermissionWithNamePojo;
import com.xbongbong.paas.pojo.ModulePermissionWithNamePojo;
import com.xbongbong.paas.pojo.PermissionComplexTermPojo;
import com.xbongbong.paas.pojo.UserDetailPojo;
import com.xbongbong.paas.pojo.dto.PermissionAppDetailDTO;
import com.xbongbong.paas.pojo.dto.PermissionModuleDetailDTO;
import com.xbongbong.paas.pojo.dto.RoleBatchAddDTO;
import com.xbongbong.paas.pojo.dto.RoleBatchDelDTO;
import com.xbongbong.paas.pojo.dto.UserAddRoleDTO;
import com.xbongbong.paas.pojo.dto.UserDelRoleDTO;
import com.xbongbong.paas.pojo.dto.UserDetailDTO;
import com.xbongbong.paas.pojo.dto.UserFormPermissionDTO;
import com.xbongbong.paas.pojo.dto.UserGetDTO;
import com.xbongbong.paas.pojo.dto.UserInfoDTO;
import com.xbongbong.paas.pojo.dto.UserListDTO;
import com.xbongbong.paas.pojo.vo.CompanyVO;
import com.xbongbong.paas.pojo.vo.FeeCompanyVO;
import com.xbongbong.paas.pojo.vo.IsActiveAliyunCallVO;
import com.xbongbong.paas.pojo.vo.RoleAppDetailVO;
import com.xbongbong.paas.pojo.vo.RoleBatchAddVO;
import com.xbongbong.paas.pojo.vo.RoleBatchDelVO;
import com.xbongbong.paas.pojo.vo.RoleModuleDetailVO;
import com.xbongbong.paas.pojo.vo.UserAddRoleVO;
import com.xbongbong.paas.pojo.vo.UserDelRoleVO;
import com.xbongbong.paas.pojo.vo.UserDetailVO;
import com.xbongbong.paas.pojo.vo.UserFormPermissionVO;
import com.xbongbong.paas.pojo.vo.UserGetVO;
import com.xbongbong.paas.pojo.vo.UserInfoVO;
import com.xbongbong.paas.pojo.vo.UserListVO;
import com.xbongbong.paas.pojo.vo.UserMembersVO;
import com.xbongbong.paas.pojo.vo.WaterMarkVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisConstant;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.service.CallCenterCommonService;
import com.xbongbong.paas.service.DataConnectionService;
import com.xbongbong.paas.service.HomePageManageService;
import com.xbongbong.paas.service.PackageService;
import com.xbongbong.paas.service.PerformanceService;
import com.xbongbong.paas.service.UserConfigService;
import com.xbongbong.paas.service.UserService;
import com.xbongbong.paas.service.WaterMarkService;
import com.xbongbong.paas.service.async.WorkHandoverAsync;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.helper.ReflectHelper;
import com.xbongbong.paas.toolbox.pojo.AppPermissionPojo;
import com.xbongbong.paas.toolbox.pojo.ModulePermissionPojo;
import com.xbongbong.paas.toolbox.pojo.PermissionTermsPojo;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.toolbox.wrap.DepartmentSimpleVO;
import com.xbongbong.paas.toolbox.wrap.DepartmentVO;
import com.xbongbong.paas.toolbox.wrap.LabelVO;
import com.xbongbong.paas.toolbox.wrap.RoleSimpleVO;
import com.xbongbong.paas.toolbox.wrap.UserSimpleVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.constant.SymbolConstant;
import com.xbongbong.pro.domain.entity.SearchCustomerCompanyEntity;
import com.xbongbong.pro.domain.entity.SysLabelEntity;
import com.xbongbong.pro.enums.AccessLinkEnum;
import com.xbongbong.pro.enums.LimitChooseRangeTypeEnum;
import com.xbongbong.pro.enums.PackageTypeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.SoukeMealEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.menu.enums.MySetMenuEnum;
import com.xbongbong.pro.enums.menu.enums.SystemAppMenuEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.model.SysLabelModel;
import com.xbongbong.pro.packageInfo.pojo.vo.BasePackageInfoVO;
import com.xbongbong.pro.permission.pojo.SetButtonPojo;
import com.xbongbong.pro.permission.pojo.dto.MySetDTO;
import com.xbongbong.pro.permission.pojo.vo.MySetVO;
import com.xbongbong.pro.process.pojo.ProcessUserListPojo;
import com.xbongbong.pro.process.pojo.dto.ProcessUserListDTO;
import com.xbongbong.pro.process.pojo.vo.ProcessUserListVO;
import com.xbongbong.pro.script.pojo.SyncUserToContactPojo;
import com.xbongbong.pro.script.pojo.dto.SyncUserToContactDTO;
import com.xbongbong.pro.statistic.pojo.vo.ChartCategoryInitVO;
import com.xbongbong.pro.user.pojo.AssistTuplePojo;
import com.xbongbong.pro.user.pojo.dto.UserAssistAddDTO;
import com.xbongbong.pro.user.pojo.dto.UserAssistDelDTO;
import com.xbongbong.pro.user.pojo.dto.UserAssistUpdateDTO;
import com.xbongbong.pro.user.pojo.dto.UserGetDataPermissionDTO;
import com.xbongbong.pro.user.pojo.dto.UserInfoAuthDTO;
import com.xbongbong.pro.user.pojo.dto.UserLetterListDTO;
import com.xbongbong.pro.user.pojo.dto.UserMaxDataPermissionDTO;
import com.xbongbong.pro.user.pojo.dto.UserMembersAddDTO;
import com.xbongbong.pro.user.pojo.dto.UserMembersGetDTO;
import com.xbongbong.pro.user.pojo.dto.WorkHandoverInfoDTO;
import com.xbongbong.pro.user.pojo.dto.WorkHandoverSaveDTO;
import com.xbongbong.pro.user.pojo.vo.UserAssistAddVO;
import com.xbongbong.pro.user.pojo.vo.UserAssistDelVO;
import com.xbongbong.pro.user.pojo.vo.UserGetDataPermissionVO;
import com.xbongbong.pro.user.pojo.vo.UserLetterGetVO;
import com.xbongbong.pro.user.pojo.vo.UserLetterListVO;
import com.xbongbong.pro.user.pojo.vo.UserMaxDataPermissionVO;
import com.xbongbong.pro.user.pojo.vo.WorkHandoverInfoVO;
import com.xbongbong.pro.user.pojo.vo.WorkHandoverSaveVO;
import com.xbongbong.pro.user.pojo.vo.WorkHandoverStatusVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.PageConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.KeFuOnLineLogEntity;
import com.xbongbong.saas.domain.entity.ProductUserEntity;
import com.xbongbong.saas.domain.entity.UserTeamEntity;
import com.xbongbong.saas.domain.entity.ext.ProductEntityExt;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.help.KnowledgeBaseHelp;
import com.xbongbong.saas.help.SaasUpdateHelp;
import com.xbongbong.saas.model.ContractUserModel;
import com.xbongbong.saas.model.CustomerUserModel;
import com.xbongbong.saas.model.KeFuOnLineLogModel;
import com.xbongbong.saas.model.OpportunityUserModel;
import com.xbongbong.saas.model.PaasFormDataModel;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.ProductUserModel;
import com.xbongbong.saas.service.UserTeamService;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.CompanyEntity;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.ProPermissionEntity;
import com.xbongbong.sys.domain.entity.RoleEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.domain.entity.WeakManageEntity;
import com.xbongbong.sys.domain.entity.ext.UserEntityExt;
import com.xbongbong.sys.enums.DataPermissionEnum;
import com.xbongbong.sys.enums.RoleEnum;
import com.xbongbong.sys.enums.UserTypeOfLetterEnum;
import com.xbongbong.sys.help.ProPermissionHelp;
import com.xbongbong.sys.help.SysEnvHelp;
import com.xbongbong.sys.model.CompanyModel;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.ProPermissionModel;
import com.xbongbong.sys.model.RoleModel;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.sys.model.WeakManageModel;
import com.xbongbong.sys.pojo.DataPermissionDetailPojo;
import com.xbongbong.sys.pojo.DataPermissionsPojo;
import com.xbongbong.sys.util.UserUtil;
import com.xbongbong.util.ContractCompareUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * @author kaka
 * @time 2018-8-28 14:11
 */
@Service("userService")
public class UserServiceImpl implements UserService {

    private static final Logger LOG = LoggerFactory.getLogger(UserServiceImpl.class);

    @Resource
    private UserModel userModel;
    @Resource
    private RoleModel roleModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private PaasMenuModel paasMenuModel;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private WeakManageModel weakManageModel;
    @Resource
    private ProPermissionModel proPermissionModel;
    @Resource
    private CustomerUserModel customerUserModel;
    @Resource
    private OpportunityUserModel opportunityUserModel;
    @Resource
    private ContractUserModel contractUserModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private PerformanceService performanceService;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private WorkHandoverAsync workHandoverAsync;
    @Resource
    private PackageService packageService;
    @Resource
    private SearchCustomerCompanyModel searchCustomerCompanyModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private CloudCodeHelp cloudCodeHelp;
    @Resource
    private DeveloperModel developerModel;
    @Resource
    private KeFuOnLineLogModel keFuOnLineLogModel;
    @Resource
    private UserInfoHelp userInfoHelp;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private SysEnvHelp sysEnvHelp;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private SyncDataToXbbFeignClient syncDataToXbbFeignClient;
    @Resource
    private UserTeamService userTeamService;
    @Resource
    private ProductUserModel productUserModel;
    @Resource
    private ProductModel productModel;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private HomePageManageService homePageManageService;
    @Resource
    private UserConfigService userConfigService;
    @Resource
    private RestTemplateHelper restTemplateHelper;
    @Resource
    private PaasFormDataModel paasFormDataModel;
    @Resource
    private SaasUpdateHelp saasUpdateHelp;
    @Resource
    private DataConnectionService dataConnectionService;
    @Resource
    private SysLabelModel sysLabelModel;
    @Resource
    private TeamRedisHelper teamRedisHelper;
    @Resource
    private WaterMarkService waterMarkService;
    @Resource
    private KnowledgeBaseHelp knowledgeBaseHelp;
    @Resource
    private CallCenterService callCenterService;
    @Resource
    private ContractCompareUtil contractCompareUtil;
    @Resource
    private CallCenterCommonService callCenterCommonService;

    /**
     * 获取用户VO信息，目前用于登录接口
     *
     * @param corpid              公司id
     * @param userId              用户id
     * @param userDetailFlag      UserVO中是否返回 Set<DepartmentVO> 和 Set<RoleVO>
     *                            默认不返回该数据，网关调用做权限判断时需要
     * @param paasPermissionsFlag 返回的用户中的 RoleVO 是否需要paasPermissions字段数据，
     *                            默认不返回该数据，网关调用做权限验证时需要
     * @return
     * @throws XbbException
     */
    @Override
    public UserVO getUserVO(String corpid, String userId, boolean userDetailFlag, boolean paasPermissionsFlag) throws XbbException {
        try {

            return userModel.getUserVO(corpid, userId, userDetailFlag, paasPermissionsFlag);
        } catch (XbbException e) {
            LOG.error("UserService.getUserVO 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
        } catch (Exception e) {
            LOG.error("UserService.getUserVO 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 获取用户基本信息
     * @param userInfoDTO 获取用户信息DTO
     * @return 获取用户基本信息
     * @throws XbbException 业务异常
     */
    @Override
    public UserInfoVO getUserInfo(UserInfoDTO userInfoDTO) throws XbbException {
        UserInfoVO userInfoVO = new UserInfoVO();
        String corpid = userInfoDTO.getCorpid();
        String userId = userInfoDTO.getUserId();

        try {
            UserEntity user = userModel.getByKey(userId, corpid);
            //用户不存在
            if(user == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
            }
            BasePackageInfoVO basePackageInfoVO = null;
            if (userInfoDTO.getCompanyInfoFlag()) {
                basePackageInfoVO = packageService.getBasePackageInfoFromRedis(corpid);
            }

            //用户信息
            UserVO userVO = new UserVO();
            BeanUtil.copyProperties(user, userVO);

            //用户复杂数据
            if (userInfoDTO.getUserDetailFlag()) {
                userModel.assembleUserVO(userVO, userInfoDTO.getPaasPermissionsFlag());
            }

            if (userInfoDTO.getCompanyInfoFlag() && basePackageInfoVO != null) {
                CompanyEntity entity = companyModel.getByKey(corpid);
                //公司信息
                CompanyVO companyVO = new CompanyVO();
                companyVO.setCorpid(corpid);
                companyVO.setCorpName(basePackageInfoVO.getCorpName());
                companyVO.setScale(basePackageInfoVO.getScale());
                companyVO.setIndustry(basePackageInfoVO.getIndustry());
                companyVO.setUserNum(basePackageInfoVO.getUserNum());
                companyVO.setCorpLogoUrl(entity.getCorpLogoUrl());
                //套餐信息
                FeeCompanyVO feeCompanyVO = new FeeCompanyVO();
                Integer feeType = basePackageInfoVO.getFeeType();
                feeCompanyVO.setFeeName(basePackageInfoVO.getFeeName());
                feeCompanyVO.setFeeTypeName(PackageTypeEnum.getNameByType(basePackageInfoVO.getFeeType()));
                feeCompanyVO.setStartTime(basePackageInfoVO.getFeeStartTime());
                feeCompanyVO.setEndTime(basePackageInfoVO.getFeeEndTime());
                feeCompanyVO.setFeeType(feeType);
                Integer isProfessionalEdition = Objects.equals(feeType, PackageTypeEnum.STANDARD.getType()) ?
                        PackageTypeEnum.STANDARD.getType() : PackageTypeEnum.ADVANCED.getType();
                feeCompanyVO.setIsProfessionalEdition(isProfessionalEdition);
                // 是否付费
                feeCompanyVO.setIsFree(basePackageInfoVO.getIsFree());

                userInfoVO.setCompany(companyVO);

                userInfoVO.setFeeCompany(feeCompanyVO);
            }
            // 超管或者有查重权限
            Boolean customerDuplicate = Objects.nonNull(userInfoDTO.getLoginUser())
                    && (userInfoDTO.getLoginUser().isAdminOrBoss() || userInfoDTO.getLoginUser().getPermSet().contains(ProPermissionAliasEnum.CUSTOMER_DUPLICATE.getAlias()));
            if (customerDuplicate) {
                userVO.setCustomerDuplicate(true);
            }

            // 超管或者有查重权限
            Boolean clueDuplicate = Objects.nonNull(userInfoDTO.getLoginUser())
                    && (userInfoDTO.getLoginUser().isAdminOrBoss() || userInfoDTO.getLoginUser().getPermSet().contains(ProPermissionAliasEnum.CLUE_DUPLICATE.getAlias()));
            if (clueDuplicate) {
                userVO.setClueDuplicate(true);
            }

            // 超管或者有查重联系人权限
            Boolean contactDuplicate = Objects.nonNull(userInfoDTO.getLoginUser())
                    && (userInfoDTO.getLoginUser().isAdminOrBoss() || userInfoDTO.getLoginUser().getPermSet().contains(ProPermissionAliasEnum.CONTACT_DUPLICATE.getAlias()));
            if (contactDuplicate) {
                userVO.setContactDuplicate(true);
            }

            boolean developer = false;
            if (basePackageInfoVO != null && Objects.equals(PackageTypeEnum.ULTIMATE.getType(), basePackageInfoVO.getFeeType())) {
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(StringConstant.CORPID, corpid);
                param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                param.put("developer", userId);
                Integer count = developerModel.getEntitysCount(param);
                developer = count >= 1;
            }
            userInfoVO.setDeveloper(developer);
            userInfoVO.setUser(userVO);
            userInfoVO.setBetaInfo(ProBaseConfig.getBetaInfo());

            // 智能客服
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("userId", userId);
            param.put("del", 0);
            List<KeFuOnLineLogEntity> logEntityList = keFuOnLineLogModel.findEntitys(param);
            Integer isDisPlay = CollectionUtils.isEmpty(logEntityList) ? Integer.valueOf(0) : Integer.valueOf(1);
            userInfoVO.setIsDisPlay(isDisPlay);

            boolean isOpenWorkflow = commonHelp.isOpenWorkFlow(corpid);
            userInfoVO.setIsOpenWorkflow(isOpenWorkflow);
            userInfoVO.setIsGray(sysEnvHelp.isGrayEnvironment());

            String officPreviewUrl = userConfigService.getOfficPreviewUrl(corpid, userId);
            userInfoVO.setOfficePreviewUrl(officPreviewUrl);

            Integer feeType = basePackageInfoVO != null ? basePackageInfoVO.getFeeType(): PackageTypeEnum.STANDARD.getType();
            boolean isCustomerPublicSeniorMode = commonHelp.isCustomerPublicPoolSeniorModelByLogin(corpid,feeType);
            userInfoVO.setIsCustomerPublicSeniorMode(isCustomerPublicSeniorMode);
            boolean isCluePublicSeniorMode = commonHelp.isCluePublicPoolSeniorModelByLogin(corpid,feeType);
            userInfoVO.setIsCluePublicSeniorMode(isCluePublicSeniorMode);
            // 水印标记
            WaterMarkVO waterMarkVO = waterMarkService.getWaterMark(corpid);
            userInfoVO.setWaterMark(waterMarkVO);
            // 知识库悬浮按钮显示
            userInfoVO.setIsShowKnowledge(knowledgeBaseHelp.isShowKnowledgeBase(userInfoDTO.getCorpid()));
            userInfoVO.setIsOpenMenuWhite(commonHelp.isOpenMenuWhite(corpid));
            userInfoVO.setIsOpenOnlineEditor(commonHelp.isOpenOnlineEditor(corpid));
            // 呼叫中心和阿里云呼
            // 钉钉平台呼叫中心坐席原从（com.xbongbong.saas.service.impl.MobileDetailServiceImpl.getPhoneForDial）中获取，moduleType为度言（已弃用）永远为false
            // 多平台呼叫中心坐席从（com.xbongbong.paas.service.impl.CallCenterCommonServiceImpl.isOpenCallAndAgent）中获取坐席
            boolean isActiveCall = false;
            if (!corpid.startsWith("ding")) {
                isActiveCall = callCenterCommonService.isOpenCallAndAgent(corpid, userId);
            }
            userInfoVO.setIsCallCenter(isActiveCall);
            boolean activeAliyunCall = callCenterCommonService.isActiveAliyunCall(corpid, userId).IsActiveAliyunAndHasRole();
            userInfoVO.setIsAliyunCallCenter(activeAliyunCall);
        } catch (XbbException xe) {
            //业务异常继续往外抛出
            throw xe;
        } catch (Exception e) {
            LOG.error("UserService.getUserInfo 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        return userInfoVO;
    }

    @Override
    public UserGetVO getUserInfoByTargetUserId(UserGetDTO userGetDTO) throws XbbException {
        return userInfoHelp.getUserInfoByTargetUserId(userGetDTO);
    }

    @Override
    public UserFormPermissionVO getUserFormPermission(UserFormPermissionDTO userFormPermissionDTO) throws XbbException {
        return userInfoHelp.getUserFormPermission(userFormPermissionDTO);
    }

    @Override
    public UserFormPermissionVO getUserFormPermissionInternal(String corpid, String userId, Long appId, Long menuId) throws XbbException {
        return userInfoHelp.getUserFormPermissionInternal(corpid, userId, appId, menuId);
    }

    @Override
    public UserFormPermissionVO getUserFormPermission(UserVO userVO, Long appId, Long menuId) throws XbbException {
        // 登录员工paas权限的并集
        String paasPermission = userVO.getPaasPermissions();
        UserFormPermissionVO formPermissionVO = new UserFormPermissionVO();
        ModulePermissionPojo formPermission = new ModulePermissionPojo();
        // 初始化该表单权限，后续通过实际该用户所具有的该表单权限进行覆盖
        PermissionTermsPojo permission = new PermissionTermsPojo();

        formPermission.setId(menuId);
        formPermission.setType(ModuleTypeEnum.FORM.getCode());

        ProPermissionHelp.getMaxPermissionTerms(permission, paasPermission, appId, menuId);
        formPermission.setPermission(permission);
        formPermissionVO.setIsAdminOrBoss(userVO.isAdminOrBoss());
        formPermissionVO.setFormPermission(formPermission);

        return formPermissionVO;
    }

    /**
     * 评论艾特的用户列表
     *
     * @param processUserListDTO
     * @return
     * @throws XbbException
     */
    @Override
    public ProcessUserListVO getProcessUserList(ProcessUserListDTO processUserListDTO) throws XbbException {
        ProcessUserListVO processUserListVO = new ProcessUserListVO();
        String keyWord =  processUserListDTO.getKeyWord();
        List<ProcessUserListPojo> processUserListPojos = new ArrayList<>();
        try {
            Map<String, Object> param = BeanUtil.convertBean2Map(processUserListDTO, true);
            param.put("nameLike", keyWord);
            if (Objects.equals(processUserListDTO.getPlatform(), PlatFormEnum.WEB.getValue())) {
                param.put("limitNum", 10);
            } else if (Objects.equals(processUserListDTO.getPlatform(), PlatFormEnum.DINGTALK.getValue())) {
                if (StringUtil.isNotEmpty(keyWord)) {
                    Integer page = processUserListDTO.getPage();
                    Integer pageSize = processUserListDTO.getPageSize();
                    if (page == null || page < 1) {
                        page = 1;
                    }
                    if (pageSize == null || pageSize < 1) {
                        pageSize = PageConstant.DEFAULT_PAGE_SIZE;
                    }
                    param.put("start", (page - 1) * pageSize);
                    param.put("pageNum", pageSize);
                }
            }

            // 排除已删除或已离职的用户
            param.put("negDel", 1);
            param.put("orderByStr", "convert(name using gbk) ASC");
            List<UserEntityExt> userList = userModel.findEntitysOrderByPinyin(param);
            List<DepartmentEntity> departmentEntities = departmentModel.findAllDepartment(processUserListDTO.getCorpid(), true);
            for (UserEntityExt user : userList) {
                ProcessUserListPojo processUserListPojo = new ProcessUserListPojo();
                processUserListPojo.setId(user.getUserId());
                processUserListPojo.setName(user.getName());
                if (Objects.equals(processUserListDTO.getPlatform(), PlatFormEnum.DINGTALK.getValue())) {
                    processUserListPojo.setAvatar(user.getAvatar());
                    if (StringUtil.isEmpty(keyWord)) {
                        processUserListPojo.setFirstPinyin(user.getFirstPinyin());
                    }
                }
                StringBuilder deptName = new StringBuilder();
                List<Long> deptIds = JSONArray.parseArray(user.getDepartment(), Long.class);
                if (deptIds == null || deptIds.size() == 0) {
                    continue;
                } else {
                    for (Long deptId : deptIds) {
                        for (DepartmentEntity depart : departmentEntities) {
                            if (Objects.equals(depart.getId(), deptId)) {
                                deptName.append(depart.getName()).append(",");
                            }
                        }
                    }
                }
                if (deptName.length() > 0) {
                    processUserListPojo.setDepartment(deptName.substring(0, deptName.length()-1));
                } else {
                    processUserListPojo.setDepartment(deptName.toString());
                }
                processUserListPojos.add(processUserListPojo);
            }
            processUserListVO.setList(processUserListPojos);
        } catch (Exception e) {
            LOG.error("UserService.list 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return processUserListVO;
    }

    /**
     * 获取用户列表
     * @param userListDTO 用户列表DTO
     * @return 用户列表VO
     * @throws XbbException 业务异常
     */
    @Override
    public UserListVO list(UserListDTO userListDTO) throws XbbException {
        UserListVO userListVO = new UserListVO();
        PageHelper pageHelper;
        List<UserEntity> userList;
        Long formId = userListDTO.getFormId();
        String attr = userListDTO.getAttr();

        try {
            Map<String, Object> param = BeanUtil.convertBean2Map(userListDTO, true);
            if (Objects.nonNull(userListDTO.getLimitChooseRange())) {
                LimitChooseRangePoJo limitChooseRangePoJo = userListDTO.getLimitChooseRange();
                LimitChooseRangeTypeEnum limitChooseRangeTypeEnum = LimitChooseRangeTypeEnum.getByType(limitChooseRangePoJo.getType());
                switch (limitChooseRangeTypeEnum) {
                    case CUSTOM:
                        List<OptionalRangeEntity> optionalRangeList = limitChooseRangePoJo.getOptionalRange();
                        if (Objects.nonNull(optionalRangeList) && !optionalRangeList.isEmpty()) {
                            List<String> userIdIn = new ArrayList<>();
                            List<String> depIdIn = new ArrayList<>();
                            List<String> roleIdIn = new ArrayList<>();
                            optionalRangeList.forEach((item) -> {
                                String id = item.getId();
                                String property = item.getProperty();
                                if (OptionalRangeEnum.USER.getValue().equals(property)
                                        || OptionalRangeEnum.DYNAMIC.getValue().equals(property)) {
                                    userIdIn.add(id);
                                } else if (OptionalRangeEnum.DEPT.getValue().equals(property)) {
                                    depIdIn.add(id);
                                } else if (OptionalRangeEnum.ROLE.getValue().equals(property)) {
                                    roleIdIn.add(id);
                                }
                            });
                            Map<String, Object> limitChooseRangeParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                            limitChooseRangeParam.put("idIn", userIdIn);
                            limitChooseRangeParam.put("depIdIn", depIdIn);
                            limitChooseRangeParam.put("roleIdIn", roleIdIn);
                            param.put("limitChooseRange", limitChooseRangeParam);
                        }
                        break;
                    case RELY:

                        break;
                    default:
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }

            }

            //过滤用户列表数据可选范围
            if (Objects.nonNull(formId) && StringUtils.isNotEmpty(attr) && formId != 0L){
                PaasFormExplainEntity paasFormExplainEntity = proFormHelp.getExplainEntity(userListDTO.getCorpid(), userListDTO.getFormId(), userListDTO.getBusinessType());
                if (Objects.nonNull(paasFormExplainEntity)) {
                    Map<String, FieldAttrEntity> thisExplainMap = ExplainUtil.getAllSubFormExplainMap(paasFormExplainEntity.getExplains());
                    FieldAttrEntity fieldAttrEntity = thisExplainMap.get(userListDTO.getAttr());
                    if (Objects.nonNull(fieldAttrEntity)){
                        LimitChooseRangePoJo limitChooseRange = fieldAttrEntity.getLimitChooseRange();
                        if (Objects.nonNull(limitChooseRange) && Objects.equals(limitChooseRange.getType(), LimitChooseRangeTypeEnum.CUSTOM.getType())){
                            //开启自定义范围筛选标记
                            userListVO.setOpenRangeFilter(1);
                            Map<String, Object> userOptionalRange = filterUserList(userListDTO, limitChooseRange);
                            if (Objects.isNull(userOptionalRange)) {
                                userListVO.setOpenRangeFilter(0);
                            } else {
                                param.put("userOptionalRange", userOptionalRange);
                            }
                        }
                    }
                }
            }

            //对departmentId 为 1 （全公司）做特殊处理
            //对departmentId 为 0 （全公司）做特殊处理 (常用团队成员加的逻辑)
            if (userListDTO.getDepartmentId() != null && (userListDTO.getDepartmentId().equals(PaasConstant.CORP_DEPARTMENT_ID) || userListDTO.getDepartmentId().equals(BasicConstant.ZERO_LONG))) {
                param.remove("departmentId");
            }
            if (!Objects.equals(userListDTO.getDelIgnore(), BasicConstant.ONE)) {
                // 排除已删除或已离职的用户
                param.put("negDel", 1);
            }
            if ( Objects.equals(userListDTO.getDelIgnore(), BasicConstant.ONE) ) {
                param.put(ParameterConstant.LEAVE_MARKS, BasicConstant.ONE);
            }
            // 部门下所有员工
            if (Objects.nonNull(userListDTO.getAllFlag()) && Objects.equals(BasicConstant.ONE, userListDTO.getAllFlag())) {
                userList = new ArrayList<>();
                // 获取部门下的全部数据
                int count = userModel.getEntitysCount(param);
                int start = 0;
                int pageNum = 2000;
                param.put("pageNum", pageNum);
                pageHelper = PageHelperUtil.getPageHelper(param, userModel, pageNum);
                for (; start <= count; start = start + pageNum) {
                    param.put("start", start);
                    List<UserEntity> list = userModel.findEntitys(param);
                    userList.addAll(list);
                }
            } else {
                pageHelper = PageHelperUtil.getPageHelper(param, userModel, userListDTO.getPageSize());
                userList = (List<UserEntity>) PageHelperUtil.getEntityList(param, pageHelper, userModel);
            }
        } catch (Exception e) {
            LOG.error("UserService.list 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        List<UserVO> userVOList = new ArrayList<>();
        try {
            BeanUtil.copyPropertiesList(userList, userVOList, UserVO.class);
        } catch (InstantiationException | IllegalAccessException e) {
            LOG.error("UserService.list 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        Set<Integer> roleIdSet = new HashSet<>();
        Set<Long> departmentIdSet = new HashSet<>();
        Set<Long> labelIdSet = new HashSet<>();
        // 计算 roleId 集合和 depId 集合用于后续查询
        for (UserVO userVO : userVOList) {
            formatRoleIdSet(userVO.getRoleIds(), roleIdSet);
            formatDepIdSet(userVO.getDepartment(), departmentIdSet);
            formatLabelIdSet(userVO.getLabels(), labelIdSet);
        }

        // 查询角色和部门
        List<RoleEntity> roleList = roleModel.getByRoleIdIn(userListDTO.getCorpid(), roleIdSet);
        List<DepartmentEntity> depList = departmentModel.getByDepIdIn(userListDTO.getCorpid(), departmentIdSet);
        // 查询标签
        List<SysLabelEntity> sysLabelEntities = sysLabelModel.getByLabelIdIn(userListDTO.getCorpid(), labelIdSet);

        Map<Integer, RoleEntity> roleMap = BeanUtil.convertListToMap(roleList, "id");
        Map<Long, DepartmentEntity> depMap = BeanUtil.convertListToMap(depList, "id");
        Map<Long, SysLabelEntity> labelMap = BeanUtil.convertListToMap(sysLabelEntities, "id");

        // 拼装用户中的角色和部门数据
        assembleUserVO(userVOList, roleMap, depMap);
        // 拼装用户数据中的系统标签
        assembleLabelUserVO(userVOList, labelMap);

        // 系统标签编辑权限
        if (Objects.nonNull(userListDTO.getLoginUser())&&userListDTO.getLoginUser().getPermSet().contains(ProPermissionAliasEnum.SYSTEM_LABEL.getAlias())) {
            userListVO.setIsEditLabel(1);
        } else {
            userListVO.setIsEditLabel(0);
        }
        userListVO.setUserList(userVOList);
        userListVO.setPageHelper(pageHelper);
        return userListVO;
    }

    private void assembleLabelUserVO(List<UserVO> userVOList, Map<Long, SysLabelEntity> labelMap) {
        List<LabelVO> labelVOS;
        for (UserVO userVO : userVOList) {
            labelVOS = new ArrayList<>();
            JSONArray labelArray = userVO.getLabels();
            if (!Objects.isNull(labelArray)) {
                for (int i = 0; i < labelArray.size(); i++) {
                    Long id = labelArray.getLong(i);
                    SysLabelEntity sysLabelEntity = labelMap.get(id);
                    if (sysLabelEntity != null) {
                        LabelVO labelVO = new LabelVO();
                        labelVO.setId(id);
                        labelVO.setColor(sysLabelEntity.getColor());
                        labelVO.setName(sysLabelEntity.getName());
                        labelVOS.add(labelVO);
                    }
                }
            }

            userVO.setLabelSet(labelVOS);
        }

    }

    private void formatLabelIdSet(JSONArray labels, Set<Long> labelIds) {
        if (Objects.isNull(labels)) {
            return;
        }
        if(labels.size() > 0) {
            for (int i = 0; i < labels.size(); i++) {
                try{
                    Long labelId = labels.getLong(i);
                    labelIds.add(labelId);
                } catch (JSONException je) {
                    LOG.error("label 字段格式错误", je);
                }
            }
        }
    }

    /**
     * 已删除人员的查询
     * @param userListDTO
     * @return
     * @throws XbbException
     */
    @Override
    public UserListVO getDisableUserList(UserListDTO userListDTO) throws XbbException {
        UserListVO userListVO = new UserListVO();
        PageHelper pageHelper;
        List<UserEntity> userList;
        try {
            Map<String, Object> param = BeanUtil.convertBean2Map(userListDTO, true);
            param.put("del", DelEnum.DELETE.getDel());
            pageHelper = PageHelperUtil.getPageHelper(param, userModel, userListDTO.getPageSize());
            userList = (List<UserEntity>) PageHelperUtil.getEntityList(param, pageHelper, userModel);
        } catch (Exception e) {
            LOG.error("UserService.getDisableUserList 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        List<UserVO> userVOList = new ArrayList<>();
        try {
            BeanUtil.copyPropertiesList(userList, userVOList, UserVO.class);
        } catch (InstantiationException | IllegalAccessException e) {
            LOG.error("UserService.getDisableUserList 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        Set<Integer> roleIdSet = new HashSet<>();
        Set<Long> departmentIdSet = new HashSet<>();
        // 计算 roleId 集合和 depId 集合用于后续查询
        for (UserVO userVO : userVOList) {
            formatRoleIdSet(userVO.getRoleIds(), roleIdSet);
            formatDepIdSet(userVO.getDepartment(), departmentIdSet);
        }
        // 查询角色和部门
        List<RoleEntity> roleList = roleModel.getByRoleIdIn(userListDTO.getCorpid(), roleIdSet);
        List<DepartmentEntity> depList = departmentModel.getByDepIdIn(userListDTO.getCorpid(), departmentIdSet);
        Map<Integer, RoleEntity> roleMap = BeanUtil.convertListToMap(roleList, "id");
        Map<Long, DepartmentEntity> depMap = BeanUtil.convertListToMap(depList, "id");
        // 拼装用户中的角色和部门数据
        assembleUserVO(userVOList, roleMap, depMap);
        userListVO.setUserList(userVOList);
        userListVO.setPageHelper(pageHelper);
        return userListVO;
    }

    /**
     * 获取组织架构用户详情
     * @param userDetailDTO 用户详情DTO
     * @return 用户列表VO
     * @throws XbbException 业务异常
     */
    @Override
    public UserDetailVO detail(UserDetailDTO userDetailDTO) throws XbbException {

        UserDetailVO userDetailVO = new UserDetailVO();
        UserDetailPojo userDetailPojo = new UserDetailPojo();

        String userId = userDetailDTO.getCheckUserId();
        String corpid = userDetailDTO.getCorpid();

        // 检查公司是否存在
        CompanyEntity companyEntity = companyModel.getByKey(corpid);
        if(companyEntity ==null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100011);
        }
        // 获取被查看用户的详细信息
        UserEntity userEntity = userModel.getByKey(userId, corpid);

        // 检查用户是否存在
        if (userEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100004);
        }


        // 处理角色和部门字段
        Set<Integer> roleIdSet = new HashSet<>();
        Set<Long> departmentIdSet = new HashSet<>();
        formatRoleIdSet(userEntity.getRoleIds(), roleIdSet);
        formatDepIdSet(userEntity.getDepartment(), departmentIdSet);

        List<RoleEntity> roleList = roleModel.getByRoleIdIn(corpid, roleIdSet);
        List<DepartmentEntity> depList = departmentModel.getByDepIdIn(corpid, departmentIdSet);

        Map<Integer, RoleEntity> roleMap = BeanUtil.convertListToMap(roleList, "id");
        Map<Long, DepartmentEntity> depMap = BeanUtil.convertListToMap(depList, "id");

        // 拼装用户中的角色和部门数据
        List<UserVO> userVOList = new ArrayList<>();
        UserVO userVO = new UserVO();
        BeanUtil.copyProperties(userEntity, userVO);
        userVOList.add(userVO);
        assembleUserVO(userVOList, roleMap, depMap);
        userVO = userVOList.get(0);

        BeanUtil.copyProperties(userEntity, userDetailPojo);
        userDetailPojo.setDepartmentConcat(userVO.getDepartmentConcat());
        userDetailPojo.setRoleConcat(userVO.getRoleConcat());

        // 如果值为空，设置默认数据 "-"
        if(StringUtil.isEmpty(userDetailPojo.getAvatar())) {
            userDetailPojo.setAvatar("/images/default.jpg");
        }
        if(StringUtil.isEmpty(userDetailPojo.getEmail())) {
            userDetailPojo.setEmail(SymbolConstant.MINUS);
        }
        if(StringUtil.isEmpty(userDetailPojo.getMobile())) {
            userDetailPojo.setMobile(SymbolConstant.MINUS);
        }
        if(StringUtil.isEmpty(userDetailPojo.getName())) {
            userDetailPojo.setName(SymbolConstant.MINUS);
        }
        if(StringUtil.isEmpty(userDetailPojo.getPosition())) {
            userDetailPojo.setPosition(SymbolConstant.MINUS);
        }

        userDetailVO.setUser(userDetailPojo);
        return userDetailVO;
    }

    @Override
    public RoleBatchDelVO roleBatchDel(RoleBatchDelDTO roleBatchDelDTO) throws XbbException {
        RoleBatchDelVO roleBatchDelVO = new RoleBatchDelVO();
        List<String> userIdList = roleBatchDelDTO.getUserIdList();
        Integer roleId = roleBatchDelDTO.getRoleId();
        String corpid = roleBatchDelDTO.getCorpid();

        //过滤 userIdList 中的空数据
        userIdList = userIdList.stream()
                .filter((String userId) -> !StringUtil.isEmpty(userId))
                .collect(Collectors.toList());

        if(userIdList.size() < 1) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002.getCode(), MessageConstant.MUST_SELECT_USER);
        }

        //不能删除管理员角色
        if (roleId.equals(RoleEnum.ADMIN.getCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.ADMIN_BATCH_DEL_MESSAGE);
        }

        //角色不存在
        RoleEntity role = roleModel.getByKey(roleId, corpid);
        if(role == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.ROLE_NOT_EXIST);
        }
        try {
            userModel.roleBathDel(corpid, userIdList, roleId);
            // 清除redis中的缓存
            removeUserRedis(corpid, userIdList);
        } catch (Exception e) {
            LOG.error("UserService.roleBatchDel 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        // 日志
        List<String> customerNameList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<UserEntity> getByUserId = userModel.getByUserId(userIdList, corpid);
        if(getByUserId.isEmpty()) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018.getCode(), ErrorMessageConstant.DELETE_USER_BE_LEAVE);
        }
        getByUserId.forEach(item -> customerNameList.add(item.getName()));
        String customerNameStr = StringUtils.join(customerNameList, "，");
        String loginUserName = roleBatchDelDTO.getLoginUserName();
        String userId = roleBatchDelDTO.getUserId();
        if(userIdList.size() > 1){
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_DELETE_ORG_ROLE), loginUserName, userIdList.size(), role.getRoleName());
            List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            InfoArrPojo infoArrPojo = new InfoArrPojo();
            infoArrPojo.setTitle(I18nMessageUtil.getMessage(I18nStringConstant.USERNAME));
            infoArrPojo.setContent(customerNameStr);
            infoArrPojoList.add(infoArrPojo);
            mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.ROLE, OperateTypeEnum.DELETE,
                    "", "", memo, roleBatchDelDTO.getHttpHeader());
        } else if(Objects.equals(userIdList.size(), 1)){
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_ORG_ROLE), loginUserName, customerNameStr, role.getRoleName());
            mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.ROLE, OperateTypeEnum.DELETE,
                    userIdList.get(0).toString(), customerNameStr, memo, roleBatchDelDTO.getHttpHeader());
        }

        return roleBatchDelVO;
    }

    @Override
    public RoleBatchAddVO roleBatchAdd(RoleBatchAddDTO roleBatchAddDTO) throws XbbException {
        RoleBatchAddVO roleBatchAddVO = new RoleBatchAddVO();
        List<String> userIdList = roleBatchAddDTO.getUserIdList();
        Integer roleId = roleBatchAddDTO.getRoleId();
        String corpid = roleBatchAddDTO.getCorpid();

        //过滤 userIdList 中的空数据
        userIdList = userIdList.stream()
                .filter((String userId) -> !StringUtil.isEmpty(userId))
                .collect(Collectors.toList());

        if(userIdList.size() < 1) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002.getCode(), MessageConstant.MUST_SELECT_USER);
        }

        //角色不存在
        RoleEntity role = roleModel.getByKey(roleId, corpid);
        if(role == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.ROLE_NOT_EXIST);
        }

        try {
            userModel.roleBathAdd(corpid, userIdList, roleId);
            // 清除redis中的缓存
            removeUserRedis(corpid, userIdList);
        } catch (Exception e) {
            LOG.error("UserService.roleBatchAdd 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        // 日志
        List<String> customerNameList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<UserEntity> getByUserId = userModel.getByUserId(userIdList, corpid);
        if(getByUserId.isEmpty()) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018.getCode(), ErrorMessageConstant.ADD_USER_BE_LEAVE);
        }
        getByUserId.forEach(item -> customerNameList.add(item.getName()));
        String customerNameStr = StringUtils.join(customerNameList, "，");
        String loginUserName = roleBatchAddDTO.getLoginUserName();
        String userId = roleBatchAddDTO.getUserId();
        if(userIdList.size() > 1){
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_ADD_ROLE), loginUserName, userIdList.size(), role.getRoleName());
            List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            InfoArrPojo infoArrPojo = new InfoArrPojo();
            infoArrPojo.setTitle(I18nMessageUtil.getMessage(I18nStringConstant.USERNAME));
            infoArrPojo.setContent(customerNameStr);
            infoArrPojoList.add(infoArrPojo);
            mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.ROLE, OperateTypeEnum.NEW,
                    "", "", memo, roleBatchAddDTO.getHttpHeader());
        } else if(Objects.equals(userIdList.size(), 1)){
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_ROLE), loginUserName, customerNameStr, role.getRoleName());
            mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.ROLE, OperateTypeEnum.NEW,
                    userIdList.get(0).toString(), customerNameStr, memo, roleBatchAddDTO.getHttpHeader());
        }

        return roleBatchAddVO;
    }

    @Override
    public UserAddRoleVO addRole(UserAddRoleDTO addRoleDTO) throws XbbException {
        UserAddRoleVO editRoleVO = new UserAddRoleVO();
        String corpid = addRoleDTO.getCorpid();
        UserVO loginUser = addRoleDTO.getLoginUser();
        Integer roleId = addRoleDTO.getRoleId();
        String roleUserId = addRoleDTO.getTargetUserId();

        RoleEntity role = roleModel.getByKey(roleId, corpid);
        if (role == null) {
           throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.ROLE_NOT_EXIST);
        }

        // 需要增加角色的用户
        UserEntity roleUser = userModel.getByKey(roleUserId, corpid);
        if (roleUser == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.USER_NOT_EXIST);
        }

        String oldUserRoleIds = roleUser.getRoleIds();
        if (StringUtil.isEmpty(oldUserRoleIds)) {
            oldUserRoleIds = PaasConstant.ROLE_DELIMITER;
        }
        List<Integer> oldRoleIdList = StringUtil.toList(oldUserRoleIds);
        if (oldRoleIdList != null && oldRoleIdList.size() > 0) {
            List<RoleEntity> oldRoles = roleModel.getByRoleIdIn(corpid, oldRoleIdList);

            // 获取现在还存在的角色id列表
            List<Integer> oldRoleIdExist = new ArrayList<>();
            for (RoleEntity oldRole : oldRoles) {
                if (oldRole != null && oldRole.getId() > 0) {
                    oldRoleIdExist.add(oldRole.getId());
                }
            }

            // 如果已有超过 10 个不能再添加角色
            if (oldRoleIdExist.size() >= PaasConstant.USER_ROLE_MAX_SIZE) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.USER_ROLE_EXCEED);
            }

            if (oldRoleIdExist.contains(roleId)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.USER_ROLE_EXIST);
            }

            if (oldRoleIdExist.isEmpty()) {
                oldUserRoleIds = PaasConstant.ROLE_DELIMITER;
            } else {
                oldUserRoleIds = StringUtil.listToString(oldRoleIdExist, PaasConstant.ROLE_DELIMITER);
            }
        }

        // 拼装新的roleIds
        String newUserRoleIds = oldUserRoleIds + role.getId() + PaasConstant.ROLE_DELIMITER;
        roleUser.setRoleIds(newUserRoleIds);

        try {
            userModel.update(roleUser);
        } catch (Exception e) {
            LOG.error("UserService.roleBatchAdd 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        editRoleVO.setTargetUserId(roleUserId);

        // 清除被编辑者redis中的UserVO缓存
        removeUserRedis(corpid, Collections.singletonList(roleUserId));
        // 记录日志
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_ROLE), loginUser.getName(), roleUser.getName(), role.getRoleName());
        mongoLogHelp.buildLog(corpid, loginUser.getUserId(), loginUser.getName(), OperateModuleTypeEnum.ROLE, OperateTypeEnum.NEW,
                roleUser.getUserId(), roleUser.getName(), memo, addRoleDTO.getHttpHeader());

        return editRoleVO;
    }

    @Override
    public UserDelRoleVO delRole(UserDelRoleDTO delRoleDTO) throws XbbException {
        UserDelRoleVO delRoleVO = new UserDelRoleVO();
        String corpid = delRoleDTO.getCorpid();
        String userId = delRoleDTO.getUserId();
        Integer roleId = delRoleDTO.getRoleId();
        String roleUserId = delRoleDTO.getTargetUserId();

        UserEntity roleUser = userModel.getByKey(roleUserId, corpid);
        if (roleUser == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.USER_NOT_EXIST);
        }

        //不能删除自己的管理员角色
        if (roleId.equals(RoleEnum.ADMIN.getCode()) && userId.equals(roleUserId)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.OWN_ADMIN_ROLE_DEL);
        }

        RoleEntity role = roleModel.getByKey(roleId, corpid);
        if (role == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.ROLE_NOT_EXIST);
        }

        List<Integer> roleIdsList = StringUtil.roleIdToListInt(roleUser.getRoleIds());

        if (roleIdsList == null || roleIdsList.size() <= 0) {
            // 没有可删除的角色
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.NO_DEL_ROLE);
        } else if(roleIdsList.size() == 1){
            // 该员工只有一个角色，不能删除
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.DEL_LAST_ROLE);
        } else if (!roleIdsList.contains(roleId)){
            // 该员工原角色列表中不存在要删除的角色
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.NO_DEL_ROLE);
        }

        // 去除角色
        roleIdsList.remove(roleId);

        // 拼装新的roleIds
        String newUserRoleIds;
        if (roleIdsList.isEmpty()) {
            newUserRoleIds = PaasConstant.ROLE_DELIMITER;
        } else {
            newUserRoleIds = StringUtil.listToString(roleIdsList, PaasConstant.ROLE_DELIMITER);
        }
        roleUser.setRoleIds(newUserRoleIds);

        try {
            userModel.update(roleUser);
        } catch (Exception e) {
            LOG.error("UserService.roleBatchAdd 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        delRoleVO.setTargetUserId(roleUserId);
        // 清除被编辑者redis中的UserVO缓存
        removeUserRedis(corpid, Collections.singletonList(roleUserId));

        // 日志
        String loginUserName = delRoleDTO.getLoginUserName();
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_ORG_ROLE), loginUserName, roleUser.getName(), role.getRoleName());
        mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.ROLE, OperateTypeEnum.DELETE,
                roleUser.getUserId(), roleUser.getName(), memo, delRoleDTO.getHttpHeader());

        return delRoleVO;
    }

    @Override
    public UserMaxDataPermissionVO maxDataPermission(UserMaxDataPermissionDTO maxDataPermissionDTO) throws XbbException, IllegalAccessException, InstantiationException {
        UserMaxDataPermissionVO maxDataPermissionVO = new UserMaxDataPermissionVO();
        String corpid = maxDataPermissionDTO.getCorpid();
        String targetUserId = maxDataPermissionDTO.getTargetUserId();

        UserEntity targetUser = userModel.getByKey(targetUserId, corpid);
        if (targetUser == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.USER_NOT_EXIST);
        }

        List<Integer> roleIdsList = StringUtil.roleIdToListInt(targetUser.getRoleIds());
        // 获取目标用户的角色列表
        List<RoleEntity> roleList = roleModel.getByRoleIdIn(corpid, roleIdsList, false);
        // 最高数据权限
        int maxDataPermission = 1;
        if (roleList != null) {
            for (RoleEntity role : roleList) {
                if (maxDataPermission == 5) {
                    break;
                }
                // 计算最高dataPermission
                if (maxDataPermission < role.getDataPermission()) {
                    maxDataPermission = role.getDataPermission();
                }
            }
        }

        /*
        1) maxDataPermission = 1 or maxDataPermission = 5 时不需要额外的数据
        2) maxDataPermission = 2 or maxDataPermission = 2 时需要查出用户主管的部门列表
        3) maxDataPermission = 4 时需要查出用户助理的部门和员工列表
         */
        if (maxDataPermission == DataPermissionEnum.DEPARTMENT.getCode() || maxDataPermission == DataPermissionEnum.DEPARTMENT_RECURSION.getCode()) {
            // 主管部门列表
            List<Long> manageDepIds = userModel.getUserBelongDeptIdList(corpid, targetUserId, true);
            List<DepartmentEntity> manageDepList = departmentModel.getByDepIdIn(corpid, manageDepIds);
            List<DepartmentSimpleVO> departmentVOS = new ArrayList<>();
            BeanUtil.copyPropertiesList(manageDepList, departmentVOS, DepartmentSimpleVO.class);

            maxDataPermissionVO.setManageDepList(departmentVOS);
        } else if (maxDataPermission == DataPermissionEnum.CUSTOM.getCode()) {
            // 助理的部门列表和员工列表

            // 助理的部门列表
            List<Long> assistDepIdList = userModel.getUserAssistDepIdList(corpid, targetUserId);
            List<DepartmentEntity> assistDepList = departmentModel.getByDepIdIn(corpid, assistDepIdList);
            List<DepartmentSimpleVO> assistDepVOS = new ArrayList<>();
            BeanUtil.copyPropertiesList(assistDepList, assistDepVOS, DepartmentSimpleVO.class);
            maxDataPermissionVO.setAssistDepList(assistDepVOS);

            // 助理的员工列表
            List<String> assistUserIdList = userModel.getUserAssistUserIdList(corpid, targetUserId);
            List<UserEntity> assistUserList = userModel.getByUserId(assistUserIdList, corpid);
            List<UserSimpleVO> assistUserVOS = new ArrayList<>();
            BeanUtil.copyPropertiesList(assistUserList, assistUserVOS, UserSimpleVO.class);
            maxDataPermissionVO.setAssistUserList(assistUserVOS);
        }

        maxDataPermissionVO.setTargetUserId(targetUserId);
        maxDataPermissionVO.setDataPermission(maxDataPermission);
        return maxDataPermissionVO;
    }


    @Override
    public UserGetDataPermissionVO getDataPermission(UserGetDataPermissionDTO userGetDataPermissionDTO) throws XbbException, IllegalAccessException, InstantiationException {
        UserGetDataPermissionVO userGetDataPermissionVO = new UserGetDataPermissionVO();

        String corpid = userGetDataPermissionDTO.getCorpid();
        String targetUserId = userGetDataPermissionDTO.getTargetUserId();

        UserEntity targetUser = userModel.getByKey(targetUserId, corpid);
        if (targetUser == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.USER_NOT_EXIST);
        }

        List<Integer> roleIdsList = StringUtil.roleIdToListInt(targetUser.getRoleIds());
        // 获取目标用户的角色列表
        List<RoleEntity> roleList = roleModel.getByRoleIdIn(corpid, roleIdsList, false);
        // 是否有自定义数据权限
        boolean isCustomer = false;
        if (roleList != null) {
            for (RoleEntity role : roleList) {
                String dataPermissionDetailStr = role.getDataPermissionDetail();
                List<DataPermissionDetailPojo> dataPermissionDetailPojos = JSON.parseArray(dataPermissionDetailStr, DataPermissionDetailPojo.class);
                if (dataPermissionDetailPojos == null) {
                    dataPermissionDetailPojos = new ArrayList<>();
                }

                if (!dataPermissionDetailPojos.isEmpty()) {
                    for (DataPermissionDetailPojo dataPermissionDetailPojo : dataPermissionDetailPojos) {
                        List<DataPermissionsPojo> permissions = dataPermissionDetailPojo.getPermissions();
                        for (DataPermissionsPojo permission : permissions) {
                            if (Objects.equals(permission.getDataPermission(), DataPermissionEnum.CUSTOM.getCode())) {
                                isCustomer = true;
                                break;
                            }
                        }
                        if (isCustomer) {
                            break;
                        }
                    }
                } else {
                    if (Objects.equals(role.getDataPermission(), DataPermissionEnum.CUSTOM.getCode())) {
                        isCustomer = true;
                        break;
                    }
                }
            }
        }

        if (isCustomer) {
            // 助理的部门列表和员工列表
            // 助理的部门列表
            List<Long> assistDepIdList = userModel.getUserAssistDepIdList(corpid, targetUserId);
            List<DepartmentEntity> assistDepList = departmentModel.getByDepIdIn(corpid, assistDepIdList);
            List<DepartmentSimpleVO> assistDepVOS = new ArrayList<>();
            BeanUtil.copyPropertiesList(assistDepList, assistDepVOS, DepartmentSimpleVO.class);
            userGetDataPermissionVO.setAssistDepList(assistDepVOS);

            // 助理的员工列表
            List<String> assistUserIdList = userModel.getUserAssistUserIdList(corpid, targetUserId);
            List<UserEntity> assistUserList = userModel.getByUserId(assistUserIdList, corpid);
            List<UserSimpleVO> assistUserVOS = new ArrayList<>();
            BeanUtil.copyPropertiesList(assistUserList, assistUserVOS, UserSimpleVO.class);
            userGetDataPermissionVO.setAssistUserList(assistUserVOS);
        }

        userGetDataPermissionVO.setTargetUserId(targetUserId);

        return userGetDataPermissionVO;
    }

    @Override
    public UserAssistAddVO addAssist(UserAssistAddDTO assistAddDTO) throws XbbException {
        UserAssistAddVO assistAddVO = new UserAssistAddVO();
        String corpid = assistAddDTO.getCorpid();
        String targetUserId = assistAddDTO.getTargetUserId();
        int type = assistAddDTO.getAssistType();
        String assistAddValue = assistAddDTO.getAssistTypeValue();

        //校验，部门助理设置且assistAddValue不是long,则不合法
        Long depId = 0L;
        if (type == 2) {
            try {
                depId = Long.parseLong(assistAddValue);
            } catch (NumberFormatException e) {
                LOG.error("addAssist 执行出现错误，assistAddDTO = " + JSON.toJSONString(assistAddDTO), e);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
        }

        Map<String, Object> param = new HashMap<>();
        param.put("corpid", corpid);
        param.put("supStaffId", targetUserId);
        param.put("type", type);
        if (type == 1) {
            //员工
            param.put("subStaffId", assistAddValue);
        }else if (type == 2) {
            //部门
            param.put("subDepId", depId);
        }
        param.put("start", 0);
        param.put("pageNum", 1);
        List<WeakManageEntity> weakManageList = weakManageModel.findEntitys(param);
        //判断弱管理表里是否已存在数据
        WeakManageEntity weakManageEntity = null;
        if (weakManageList != null && weakManageList.size()>0) {
            //存在
            weakManageEntity = weakManageList.get(0);
        }
        int now = DateUtil.getInt();
        if (weakManageEntity == null) {
            weakManageEntity = new WeakManageEntity();
            weakManageEntity.setAddTime(now);
            weakManageEntity.setCorpid(corpid);
            weakManageEntity.setSupStaffId(targetUserId);
        }

        weakManageEntity.setUpdateTime(now);
        weakManageEntity.setSubStaffId(assistAddValue);
        weakManageEntity.setSubDepId(depId);
        weakManageEntity.setType(type);
        weakManageEntity.setDel(0);

        try {
            weakManageModel.save(weakManageEntity);
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, ErrorMessageConstant.SAVE_ERROR);
        }

        // TODO 日志

        return assistAddVO;
    }

    @Override
    public UserAssistDelVO delAssist(UserAssistDelDTO assistDelDTO) throws XbbException {
        UserAssistDelVO assistDelVO = new UserAssistDelVO();
        String corpid = assistDelDTO.getCorpid();
        String targetUserId = assistDelDTO.getTargetUserId();
        int type = assistDelDTO.getAssistType();
        String assistAddValue = assistDelDTO.getAssistTypeValue();

        //校验，部门助理设置且assistAddValue不是long,则不合法
        Long depId = 0L;
        if (type == 2) {
            try {
                depId = Long.parseLong(assistAddValue);
            } catch (NumberFormatException e) {
                LOG.error("delAssist 执行出现错误，assistDelDTO = " + JSON.toJSONString(assistDelDTO), e);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
        }

        Map<String, Object> param = new HashMap<>();
        param.put("corpid", corpid);
        param.put("supStaffId", targetUserId);
        param.put("type", type);
        if (type == 1) {
            //员工
            param.put("subStaffId", assistAddValue);
        }else if (type == 2) {
            //部门
            param.put("subDepId", depId);
        }
        param.put("start", 0);
        param.put("pageNum", 1);
        List<WeakManageEntity> weakManageList = weakManageModel.findEntitys(param);
        //判断弱管理表里是否已存在数据
        WeakManageEntity weakManageEntity = null;
        if (weakManageList != null && weakManageList.size()>0) {
            //存在
            weakManageEntity = weakManageList.get(0);
        }
        if (weakManageEntity == null) {
            // 不用管，说明数据库中都不存在，当做删除成功
            return assistDelVO;
        }

        weakManageModel.deleteByKey(weakManageEntity.getId(), corpid);

        // TODO 日志

        return assistDelVO;
    }

    @Override
    public BaseVO updateAssist(UserAssistUpdateDTO assistUpdateDTO) throws XbbException {
        BaseVO updateAssistVO = new BaseVO();
        String corpid = assistUpdateDTO.getCorpid();
        String targetUserId = assistUpdateDTO.getTargetUserId();
        List<AssistTuplePojo> assistTupleList = assistUpdateDTO.getAssistTuple();
        // 助理范围，部门+员工记录条数不能大于500条记录
        if (assistTupleList.size() > 500) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100075);
        }

        // 计算要插入的数据
        List<WeakManageEntity> weakManageEntities = new ArrayList<>();
        if (assistTupleList.size() > 0) {
            for (AssistTuplePojo assistTuple : assistTupleList) {
                WeakManageEntity weakManage = new WeakManageEntity();
                if (assistTuple.getAssistType().equals(1)) {
                    weakManage.setSubDepId(0L);
                    weakManage.setSubStaffId(assistTuple.getAssistTypeValue());
                } else if (assistTuple.getAssistType().equals(2)) {
                    weakManage.setSubDepId(Long.parseLong(assistTuple.getAssistTypeValue()));
                    weakManage.setSubStaffId("0");
                } else {
                    continue;
                }
                weakManage.setCorpid(corpid);
                weakManage.setSupStaffId(targetUserId);
                weakManage.setType(assistTuple.getAssistType());

                weakManageEntities.add(weakManage);
            }
        }
        // 将原助理范围数据删除，然后进行新数据批量插入
        weakManageModel.physicalDeleteBySupId(corpid, targetUserId);
        if (!weakManageEntities.isEmpty()) {
            try {
                weakManageModel.insertBatch(weakManageEntities);
            } catch (Exception e) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, ErrorMessageConstant.SAVE_ERROR);
            }
        }

        return updateAssistVO;
    }

    @Override
    public UserLetterListVO letterList(UserLetterListDTO userLetterListDTO) throws XbbException {
        UserLetterListVO userLetterListVO = new UserLetterListVO();
        try {
            UserEntity userEntity = userModel.getByKey(userLetterListDTO.getUserId(), userLetterListDTO.getCorpid());
            if(userEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            //下属条件
            Integer dataPermission = userModel.getDataPermission(userEntity, true);
            List<String> userIdIn = getUserIdIn(userLetterListDTO, userEntity, dataPermission);
            Integer viewPermission = userLetterListDTO.getViewPermission();

            String corpid = userLetterListDTO.getCorpid();
            Long departmentId = userLetterListDTO.getDepartmentId();
            if (Objects.nonNull(departmentId) && departmentId > 0) {
                // 获取所有部门
                List<DepartmentEntity> departmentList = departmentModel.findAllDepartment(corpid, false);
                if(departmentList == null) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                Set<Long> departmentSet = getSubDepIdList(departmentId, departmentList);
                List<Long> depIdSet = departmentModel.getSubDepIdList(corpid, departmentSet, false);
                userIdIn = userModel.getDepUserIdList(corpid, depIdSet, viewPermission);
                List<String> userIdList = userModel.getSubIdListByDataPermission(dataPermission, userLetterListDTO.getUserId(), userLetterListDTO.getCorpid(), viewPermission, true);
                userIdList.add(userEntity.getUserId());
                userIdIn.retainAll(userIdList);
            }
            List<UserEntityExt> subUserList =new ArrayList<>();
            if (!userIdIn.isEmpty()) {
                Map<String, Object> param = BeanUtil.convertBean2Map(userLetterListDTO, true);
                param.put("userIdIn", userIdIn);
                param.put("orderByStr", "firstPinyin ASC");
                subUserList = userModel.findEntitysOrderByPinyin(param);
                if(!subUserList.isEmpty()){
                    String flagP="";
                    for(UserEntityExt user:subUserList){
                        String fp=user.getFirstPinyin();
                        if("".equals(fp)){
                            fp="#";
                        }
                        if(!fp.equals(flagP)){
                            user.setIsFirstFp(1);
                        }
                        flagP=fp;
                    }
                }
            }
            List<UserLetterGetVO> userArray = new ArrayList<>();
            for(UserEntityExt user:subUserList){
                UserLetterGetVO userLetterGetVO = new UserLetterGetVO();
                userLetterGetVO.setUserId(user.getUserId());
                userLetterGetVO.setName(user.getName());
                userLetterGetVO.setFirstPinyin(user.getFirstPinyin());
                userLetterGetVO.setIsFirstFp(user.getIsFirstFp());
                userLetterGetVO.setAvatar(user.getAvatar());
                userArray.add(userLetterGetVO);
            }
            userLetterListVO.setUserArray(userArray);
        } catch (Exception e) {
            LOG.error("UserService.letterList 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return userLetterListVO;
    }

    @Override
    public WorkHandoverInfoVO getWorkHandoverInfo(WorkHandoverInfoDTO handoverInfoDTO) throws XbbException {
        WorkHandoverInfoVO handoverInfoVO = new WorkHandoverInfoVO();
        String corpid = handoverInfoDTO.getCorpid();
        // 交接工作的员工userId
        String fromUserId = handoverInfoDTO.getFromUserId();

        UserEntity fromUser = userModel.getByKey(fromUserId, corpid);
        if (fromUser == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100065);
        }

        Map<String, Object> param = new HashMap<>();
        param.put("corpid", corpid);
        param.put("del", 0);
        param.put("userId", fromUserId);
        // 主负责人
        param.put("isMain", 1);

        // 客户数量
        Integer customerCount = customerUserModel.getEntitysCount(param);
        // 机会数量
        Integer opportunityCount = opportunityUserModel.getEntitysCount(param);
        // 合同数量
        Integer contractCount = contractUserModel.getEntitysCount(param);

        handoverInfoVO.setCustomerCount(customerCount);
        handoverInfoVO.setOpportunityCount(opportunityCount);
        handoverInfoVO.setContractCount(contractCount);
        return handoverInfoVO;
    }

    @Override
    public WorkHandoverSaveVO workHandoverSave(WorkHandoverSaveDTO handoverSaveDTO) throws XbbException {
        WorkHandoverSaveVO handoverSaveVO = new WorkHandoverSaveVO();
        String corpid = handoverSaveDTO.getCorpid();
        // 操作人
        String userId = handoverSaveDTO.getUserId();
        // 交接工作的员工userId
        String fromUserId = handoverSaveDTO.getFromUserId();
        // 交接目标员工userId
        String toUserId = handoverSaveDTO.getToUserId();

        String loginUserName = handoverSaveDTO.getLoginUserName();

        UserEntity fromUser = userModel.getByKey(fromUserId, corpid);
        UserEntity toUser = userModel.getByKey(toUserId, corpid);
        if (fromUser == null || toUser == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100065, ErrorMessageConstant.EMPLOYEE_NOT_EXIST_OR_LEAVE);
        }

        String redisKey = corpid + "_" + userId;
        String workHandoverStatus = paasRedisHelper.getValue(RedisPrefixConstant.WORK_HANDOVER, redisKey);

        /*
         * 1.成功，2，正在执行交接 >2 错误信息
         */
        if(workHandoverStatus != null) {
            if ("2".equals(workHandoverStatus)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100003, ErrorMessageConstant.TRANSFER_TASK_IN_PROGRESS);
            }
        }

        /*
         * 移交任务，起线程
         * @Async
         */
        workHandoverAsync.workHandoverThread(corpid, userId, fromUser, toUser,loginUserName);

        // 日志
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_HANDOVER_WORK), loginUserName, fromUser.getName(), toUser.getName());
        mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.ORGANIZATIONAL_STRUCTURE, OperateTypeEnum.HANDOVER,
                toUser.getId().toString(), toUser.getName(), memo, handoverSaveDTO.getHttpHeader());
        return handoverSaveVO;
    }

    @Override
    public WorkHandoverStatusVO getWorkHandoverStatus(BaseDTO baseDTO) throws XbbException {
        WorkHandoverStatusVO handoverStatusVO = new WorkHandoverStatusVO();
        String corpid = baseDTO.getCorpid();
        String userId = baseDTO.getUserId();

        String redisKey = corpid + "_" + userId;
        String workHandoverStatus = paasRedisHelper.getValue(RedisPrefixConstant.WORK_HANDOVER, redisKey);

        if (workHandoverStatus == null) {
            handoverStatusVO.setStatus(0);
        } else {
            try {
                Integer status = Integer.valueOf(workHandoverStatus);
                handoverStatusVO.setStatus(status);
            } catch (Exception e) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
        }

        return handoverStatusVO;
    }


    //==================== private method ====================

    /**
     * 获取下属条件
     * @param userLetterListDTO
     * @param userEntity
     * @param dataPermission
     * @return
     * @throws XbbException
     */
    private List<String> getUserIdIn(UserLetterListDTO userLetterListDTO, UserEntity userEntity, Integer dataPermission) throws XbbException {
        //下属条件
        List<String> userIdIn = new ArrayList<>();
        try {
            Integer viewPermission = userLetterListDTO.getViewPermission();
            Integer type = userLetterListDTO.getType();
            UserTypeOfLetterEnum userTypeOfLetterEnum = UserTypeOfLetterEnum.getByType(type);
            switch (userTypeOfLetterEnum) {
                case ALL:
                    userIdIn = userModel.getSubIdListByDataPermission(dataPermission, userEntity.getUserId(), userEntity.getCorpid(), viewPermission, true);
                    userIdIn.add(userEntity.getUserId());
                    break;
                case UNDERLING:
                    //下属
                    userIdIn = userModel.getSubIdListByDataPermission(dataPermission, userEntity.getUserId(), userEntity.getCorpid(), viewPermission, true);
                    break;
                case SELF:
                    //自己
                    userIdIn.add(userEntity.getUserId());
                    break;
                default:
                    //默认全部
                    userIdIn = userModel.getSubIdListByDataPermission(dataPermission, userEntity.getUserId(), userEntity.getCorpid(), viewPermission, true);
                    userIdIn.add(userEntity.getUserId());
                    break;
            }
        }catch (Exception e) {
            LOG.error("UserService.getUserIdIn 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return userIdIn;
    }


    /**
     * 获取部门id路由对应的部门
     * @param depId 部门id
     * @param departmentList 部门列表
     * @return
     */
    @Override
    public Set<Long> getSubDepIdList(Long depId, List<DepartmentEntity> departmentList) {
        return UserUtil.getSubDepIdList(depId, departmentList);
    }

    /**
     * 将某个用户对应的角色id放入角色id集合 roleIdSet中
     * @param roleIds 某个用户表中的roleIds |1|2|格式
     * @param roleIdSet 角色id集合
     */
    private void formatRoleIdSet(String roleIds, Set<Integer> roleIdSet) {
        userInfoHelp.formatRoleIdSet(roleIds, roleIdSet);
    }

    /**
     * 将某个用户对应的部门id放入部门id集合 departmentIdSet 中
     * @param department 某个用户所在的部门id数组，[1,2]格式
     * @param departmentIdSet 部门id集合
     */
    private void formatDepIdSet(String department, Set<Long> departmentIdSet) {
        if (StringUtil.isEmpty(department)) {
            // department为空 异常数据可以记点日志
            return;
        }
        JSONArray depArr = JSON.parseArray(department);
        if(depArr != null && depArr.size() > 0) {
            for (int i = 0; i < depArr.size(); i++) {
                try{
                    Long depId = depArr.getLong(i);
                    departmentIdSet.add(depId);
                } catch (JSONException je) {
                    LOG.error("department 字段格式错误", je);
                }
            }
        }
    }



    /**
     * 拼装用户中的 角色和部门数据
     * @param userVOList 待拼装的用户VO列表
     * @param roleMap 用户VO对应的角色Map
     * @param depMap 用户VO对应的部门Map
     */
    private void assembleUserVO(List<UserVO> userVOList,  Map<Integer, RoleEntity> roleMap, Map<Long, DepartmentEntity> depMap) {
        Set<RoleSimpleVO> roleSet;
        Set<DepartmentVO> depSet;
        RoleEntity tmpRole;
        DepartmentEntity tmpDep;
        for (UserVO userVO : userVOList) {
            String roleIds = userVO.getRoleIds();
            String department = userVO.getDepartment();

            // 用户具有的角色名拼接值
            StringBuilder roleConcat = new StringBuilder();
            StringBuilder departmentConcat = new StringBuilder();
            roleSet = new HashSet<>();
            depSet = new HashSet<>();
            if (!StringUtil.isEmpty(roleIds)) {
                String[] roleIdArr = roleIds.split("\\|");
                for (String roleId : roleIdArr) {
                    if (StringUtil.isEmpty(roleId)) {
                        continue;
                    }
                    tmpRole = roleMap.get(Integer.valueOf(roleId));
                    if (tmpRole != null) {
                        RoleSimpleVO roleVO = new RoleSimpleVO();
                        BeanUtil.copyProperties(tmpRole, roleVO);
                        roleSet.add(roleVO);
                        // 拼接角色名，英文逗号(,)分隔
                        roleConcat.append(tmpRole.getRoleName()).append(",");
                    }
                }
            }

            if (!StringUtil.isEmpty(department)) {
                JSONArray depArr = JSON.parseArray(department);
                if(depArr != null && depArr.size() > 0) {
                    for (int i = 0; i < depArr.size(); i++) {
                        try{
                            Long depId = depArr.getLong(i);
                            tmpDep = depMap.get(depId);
                            if(tmpDep != null) {
                                DepartmentVO departmentVO = new DepartmentVO();
                                BeanUtil.copyProperties(tmpDep, departmentVO);
                                depSet.add(departmentVO);
                                // 拼接角色名，英文逗号(,)分隔
                                departmentConcat.append(tmpDep.getName()).append(",");
                            }
                        } catch (JSONException je) {
                            LOG.error("corpid = " + userVO.getCorpid() + ",userId = " + userVO.getUserId() + " department 字段格式错误", je);
                        }
                    }
                }
            }

            String roleConcatStr = roleConcat.toString();
            String departmentConcatStr = departmentConcat.toString();
            if (roleConcatStr.length() > 0) {
                roleConcatStr = roleConcatStr.substring(0, roleConcatStr.length() - 1);
            }
            if (departmentConcatStr.length() > 0) {
                departmentConcatStr = departmentConcatStr.substring(0, departmentConcatStr.length() - 1);
            }

            userVO.setRoleSet(roleSet);
            userVO.setDepSet(depSet);
            userVO.setRoleConcat(roleConcatStr);
            userVO.setDepartmentConcat(departmentConcatStr);
        }
    }

    /**
     * @Description 过滤用户列表可选范围
     * @param
     * @return java.util.List<com.xbongbong.paas.toolbox.wrap.UserVO>
     * @author sunshaoxiang
     **/
    private Map<String, Object> filterUserList(UserListDTO userListDTO, LimitChooseRangePoJo limitChooseRange) throws XbbException {
        List<String> userIdIn = null;
        List<String> userIdNoIn = null;
        List<Long> deptIdIn = null;
        List<Long> deptIdNoIn = null;
        List<Integer> roleIdIn = null;
        List<Integer> roleIdNoIn = null;
        StringBuilder roleIn = new StringBuilder();
        StringBuilder roleNoIn = new StringBuilder();
        List<ProductUserEntity> productUserList = new ArrayList<>();
        Long productId = userListDTO.getDataId();
        Map<String, Object> productUserParams = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, Object> userOptionalRange = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        UserInfoDTO loginUserInfo = new UserInfoDTO();
        PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
        try {
            //当前端传不到动态字段的数据，从数据库取
            if (Objects.nonNull(userListDTO.getDataId()) && !Objects.equals(userListDTO.getDataId(), 0L)
                    && !Objects.equals(userListDTO.getBusinessType(), XbbRefTypeEnum.CUSTOMER_COMMUNICATE.getCode()) ){
                if (Objects.equals(userListDTO.getSaasMark(), SaasMarkEnum.PAAS.getCode())) {
                    paasFormDataEntity = paasFormDataModel.getByKey(userListDTO.getDataId(), userListDTO.getCorpid());
                } else {
                    paasFormDataEntity = saasUpdateHelp.getFormData(userListDTO.getDataId(), userListDTO.getCorpid(), userListDTO.getBusinessType());
                }
                if (Objects.isNull(paasFormDataEntity)) {
                    return null;
                }
            }
            //特殊处理后端取可见部门的数据
            ProductEntityExt product = productModel.getByKey(productId, userListDTO.getCorpid());
            if (Objects.nonNull(product)) {
                JSONObject dataList = product.getData();
                Long parentId = FastJsonHelper.getLongOrDefaultFromFormData(dataList, ProductEnum.PARENT_ID.getAttr(), 0L);
                if (!Objects.equals(parentId, 0L)) {
                    productId = parentId;
                }
                productUserParams.put(ParameterConstant.CORPID, userListDTO.getCorpid());
                productUserParams.put(ParameterConstant.PRODUCT_ID, productId);
                productUserParams.put("del", 0);
                productUserList = productUserModel.findEntitys(productUserParams);
            }
            //获取负责人协同人团队
            Map<Integer, List<UserTeamEntity>> userTeam = userTeamService.getUserTeam(userListDTO.getDataId(), userListDTO.getCorpid(), userListDTO.getBusinessType());
            loginUserInfo.setLoginUser(userListDTO.getLoginUser());
            if(Objects.nonNull(limitChooseRange) && Objects.equals(limitChooseRange.getType(), LimitChooseRangeTypeEnum.CUSTOM.getType())) {
                List<FilterConditionsPoJo> filterConditions = limitChooseRange.getFilterConditions();
                if (CollectionsUtil.isNotEmpty(filterConditions)){
                    for (FilterConditionsPoJo item : filterConditions) {
                        UserDeptOptionalRangeHandler handlerByFieldType = UserDeptOptionalRangeFactory.getHandlerByFieldType(item.getFieldType());
                        Map userMap = handlerByFieldType.filterDeptUserData(item, userListDTO.getOptionalRangeDataList(), paasFormDataEntity, userTeam, productUserList, loginUserInfo);
                        if (Objects.nonNull(userMap)){
                            if (Objects.nonNull(userMap.get("userIdIn"))){
                                if (Objects.isNull(userIdIn)){
                                    userIdIn = (List)userMap.get("userIdIn");
                                }else {
                                    userIdIn.retainAll((List)userMap.get("userIdIn"));
                                }
                            }
                            if (Objects.nonNull(userMap.get("userIdNoIn"))){
                                if (Objects.isNull(userIdNoIn)){
                                    userIdNoIn = (List)userMap.get("userIdNoIn");
                                }else {
                                    userIdNoIn.addAll((List)userMap.get("userIdNoIn"));
                                    userIdNoIn = userIdNoIn.stream().distinct().collect(Collectors.toList());
                                }
                            }
                            if (Objects.nonNull(userMap.get("deptIdIn"))){
                                if (Objects.isNull(deptIdIn)){
                                    deptIdIn = (List)userMap.get("deptIdIn");
                                }else {
                                    deptIdIn.retainAll((List)userMap.get("deptIdIn"));
                                }
                            }
                            if (Objects.nonNull(userMap.get("deptIdNoIn"))){
                                if (Objects.isNull(deptIdNoIn)){
                                    deptIdNoIn = (List)userMap.get("deptIdNoIn");
                                }else {
                                    deptIdNoIn.addAll((List)userMap.get("deptIdNoIn"));
                                    deptIdNoIn =  deptIdNoIn.stream().distinct().collect(Collectors.toList());
                                }
                            }
                            if (Objects.nonNull(userMap.get("roleIdIn"))){
                                if (Objects.isNull(roleIdIn)){
                                    roleIdIn = (List)userMap.get("roleIdIn");
                                }else {
                                    roleIdIn.retainAll((List)userMap.get("roleIdIn"));
                                }
                            }
                            if (Objects.nonNull(userMap.get("roleIdNoIn"))){
                                if (Objects.isNull(roleIdNoIn)){
                                    roleIdNoIn = (List)userMap.get("roleIdNoIn");
                                }else {
                                    roleIdNoIn.addAll((List)userMap.get("roleIdNoIn"));
                                    roleIdNoIn = roleIdNoIn.stream().distinct().collect(Collectors.toList());
                                }
                            }
                        }

                    }
                    if (Objects.nonNull(userIdIn)){
                        if (Objects.nonNull(userIdNoIn)){
                            userIdIn.removeAll(userIdNoIn);
                        }
                        userOptionalRange.put("userIdIn", userIdIn);
                    }else{
                        userOptionalRange.put("userIdNoIn", userIdNoIn);
                    }
                    if (Objects.nonNull(deptIdIn)){
                        if (Objects.nonNull(deptIdNoIn)){
                            deptIdIn.removeAll(deptIdNoIn);
                        }
                        userOptionalRange.put("deptIdIn", deptIdIn );
                    }else{
                        userOptionalRange.put("deptIdNoIn", deptIdNoIn);
                    }
                    //处理role 拼接正则查询的字符串
                    if (Objects.nonNull(roleIdIn)){
                        if (Objects.nonNull(roleIdNoIn)){
                            roleIdIn.removeAll(roleIdNoIn);
                        }
                        for (int i = 0; i < roleIdIn.size(); i++) {
                            if (i > 0) {
                                roleIn.append("|");
                            }
                            roleIn.append("\\|").append(roleIdIn.get(i)).append("\\|");
                        }
                    }else if (Objects.nonNull(roleIdNoIn)){
                        for (int i = 0; i < roleIdNoIn.size(); i++) {
                            if (i > 0) {
                                roleNoIn.append("|");
                            }
                            roleNoIn.append("\\|").append(roleIdNoIn.get(i)).append("\\|");
                        }
                    }
                    if (Objects.nonNull(roleIdIn)){
                        if (StringUtil.isNotEmpty(roleIn.toString())){
                            userOptionalRange.put("roleIn", roleIn.toString());
                        }else {
                            //特殊处理，当成员角色任意一个的条件集合为空时,返回空数据
                            userOptionalRange.put("roleIn", "--");
                        }
                    }else if (StringUtil.isNotEmpty(roleNoIn.toString())){
                        userOptionalRange.put("roleNoIn", roleNoIn.toString());
                    }
                }
            }
        } catch (Exception e) {
            LOG.error("UserService.filterUserList 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        return userOptionalRange;
    }
    /**
     * 更新用户角色，清除用户缓存
     * @param corpid
     * @param userIdList
     */
    private void removeUserRedis(String corpid, List<String> userIdList) {
        for(String userId :userIdList) {
            String userKey = corpid + "____" + userId;
            paasRedisHelper.removeValue(RedisPrefixConstant.PAAS_LOGIN_USER_INFO, userKey);
        }
    }

    @Override
    public MySetVO mySet(MySetDTO mySetDTO) throws XbbException {
        MySetVO mySetVO = new MySetVO();
        UserVO userVO = mySetDTO.getLoginUser();
        List<SetButtonPojo> list = new ArrayList<>();

        addSetButton(list, MySetMenuEnum.COMMON_FORM_MANAGE);

        addSetButton(list, MySetMenuEnum.MENU_MODE_SET);

        addSetButton(list, MySetMenuEnum.FAST_NEW_SET);

        // 是否是专注模式
        boolean isFocus = userConfigService.isFocus(mySetDTO);

        // 被分配
        if (!homePageManageService.judgeDistributeByUserId(mySetDTO)){
            MySetMenuEnum mySetMenuEnum = MySetMenuEnum.CUSTOMIZE_INDEX_SET;
            mySetMenuEnum.setAccessLinkEnum(AccessLinkEnum.CUSTOMIZE_INDEX_SET);
            if (isFocus){
                mySetMenuEnum.setAccessLinkEnum( AccessLinkEnum.WORK_BOARD_SET);
            }
            addSetButton(list,mySetMenuEnum);
        }


        String corpid = mySetDTO.getCorpid();
        String userId = mySetDTO.getUserId();
        UserEntity userEntity = userModel.getByKey(userId, corpid);
        if (userEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100004, SystemErrorCodeEnum.API_ERROR_100004.getMsg());
        }

        if (performanceService.canSetPerformanceInMobile(userEntity)){
            addSetButton(list, MySetMenuEnum.PERFORMANCE_SET);
        }

        if (ProPermissionHelp.hasThisPermission(userVO, ProPermissionAliasEnum.SIGN_IN_SET.getAlias())){
            addSetButton(list, MySetMenuEnum.SIGN_IN_SET);
        }

        IsActiveAliyunCallVO activeAliyunCall = callCenterService.isActiveAliyunCall(corpid, userId);
        if (Objects.nonNull(activeAliyunCall) && Objects.equals(BasicConstant.ZERO, activeAliyunCall.getFacilitators()) && activeAliyunCall.isActiveAliyunCall()) {
            addSetButton(list, MySetMenuEnum.ALIYUN_CALLCCENTER_SET);
        }
        mySetVO.setList(list);
        return mySetVO;
    }

    private void addSetButton(List<SetButtonPojo> list, MySetMenuEnum mySetMenuEnum) {
        SetButtonPojo setButtonPojo = new SetButtonPojo();
        setButtonPojo.setUrl(mySetMenuEnum.getAccessLinkEnum().getMobileUrl());
        setButtonPojo.setName(mySetMenuEnum.getName());
        list.add(setButtonPojo);
    }


    @Override
    public RoleModuleDetailVO permissionModuleDetail(PermissionModuleDetailDTO permissionModuleDetailDTO) throws XbbException {
        String userId = permissionModuleDetailDTO.getUserId();
        String corpid = permissionModuleDetailDTO.getCorpid();
        Long appId = permissionModuleDetailDTO.getAppId();
        Integer saasMark = permissionModuleDetailDTO.getSaasMark();
        String selectUserId = permissionModuleDetailDTO.getSelectUserId();

        RoleModuleDetailVO roleModuleDetailVO = new RoleModuleDetailVO();

        UserEntity userEntity = userModel.getByKeyIngoreDel(selectUserId, corpid);
        List<Integer> roleIds = userEntity.roleIdsToList();
        List<RoleEntity> roleEntityList = roleModel.getByRoleIdIn(corpid, roleIds, true);

        List<ModulePermissionWithNamePojo> allModulePermissions;
        if (saasMark.equals(SaasMarkEnum.SAAS.getCode())) {
            allModulePermissions = aggregationSaasPermissionDetail(corpid, appId, roleEntityList);
        } else {
            allModulePermissions = aggregationPaasPermissionDetail(corpid, appId, roleEntityList);
        }
        roleModuleDetailVO.setAppId(appId);
        roleModuleDetailVO.setSaasMark(saasMark);
        roleModuleDetailVO.setModules(allModulePermissions);
        return roleModuleDetailVO;
    }

    /**
     * Description: 聚合paas应用的权限详情
     * @param corpid
     * @param appId
     * @param roleEntityList
     * @return java.util.List<com.xbongbong.paas.pojo.ModulePermissionWithNamePojo>
     * @author 魏荣杰
     * @date 2020/5/12 6:34 下午
     */
    private List<ModulePermissionWithNamePojo> aggregationPaasPermissionDetail(String corpid, Long appId, List<RoleEntity> roleEntityList) {
        List<ModulePermissionWithNamePojo> allModulePermissions = new ArrayList<>() ;
        // 查找某应用下所有模块
        Map<String, Object> params = new HashMap<>(16);
        params.put("corpid", corpid);
        params.put("appId", appId);
        params.put("del", 0);
        params.put("typeIn", Arrays.asList(2, 3, 4));
        params.put("orderByStr", "sort");
        List<PaasMenuEntity> allModules = paasMenuModel.list(params);

        for (RoleEntity role : roleEntityList) {
            // 当前的role的permission
            List<ModulePermissionWithNamePojo> nowModulePermissions = new ArrayList<>();

            String dataPermissionDetailStr = role.getDataPermissionDetail();
            List<DataPermissionDetailPojo> dataPermissionDetailPojos = JSON.parseArray(dataPermissionDetailStr, DataPermissionDetailPojo.class);
            if (dataPermissionDetailPojos == null) {
                dataPermissionDetailPojos = new ArrayList<>();
            }
            Map<Long, Integer> idAndDataPermissionMap = new HashMap<>();
            for (DataPermissionDetailPojo pojo : dataPermissionDetailPojos) {
                if (Objects.equals(appId, pojo.getId())) {
                    List<DataPermissionsPojo> permissions = pojo.getPermissions();
                    for (DataPermissionsPojo dataPermissionsPojo : permissions) {
                        idAndDataPermissionMap.put(dataPermissionsPojo.getId(), dataPermissionsPojo.getDataPermission());
                    }
                }
            }

            // 解析appPermissionPojo
            List<AppPermissionPojo> enableAppPermissions = JSON.parseArray(role.getPaasPermissions(), AppPermissionPojo.class);
            // 找到对应的appPermissionPojo
            AppPermissionPojo thisApp = null;
            if (enableAppPermissions == null) {
                enableAppPermissions = new ArrayList<>();
            }
            for (AppPermissionPojo enableApp : enableAppPermissions) {
                if (appId.equals(enableApp.getAppId())) {
                    thisApp = enableApp;
                    break;
                }
            }

            Map<Long, ModulePermissionPojo> enableModules = null;
            if (thisApp != null && thisApp.getModules() != null) {
                // 将module转化为有权限的module Map
                enableModules = new HashMap<>(16);
                for (ModulePermissionPojo enableModule : thisApp.getModules()) {
                    if (enableModule != null) {
                        enableModules.put(enableModule.getId(), enableModule);
                    }
                }
            }

            // 模块数据权限,拼装数据
            List<PermissionComplexTermPojo> modulePerms = new ArrayList<>();
            for (PaasMenuEntity module : allModules) {
                Long id = module.getId();
                // 初始化默认paas模块权限
                if (!cloudCodeHelp.isCloudCodeAlias(module.getAlias())) {
                    modulePerms = PermissionHelp.initDefaultPaasModulePermission();
                }
                cloudCodeHelp.addCloudCodePermission(corpid, appId, id, modulePerms);
                ModulePermissionWithNamePojo modulePojo = new ModulePermissionWithNamePojo();
                modulePojo.setId(id);
                modulePojo.setName(module.getName());
                modulePojo.setType(module.getType());
                modulePojo.setSaasMark(SaasMarkEnum.PAAS.getCode());
                // 默认设为 false, PermissionTermsPojo初始化,没有设置数据时传回初始值
                modulePojo.setEnable(false);

                Set<String> dynamicPermissionSet = cloudCodeHelp.getDynamicPermissionSet(role.getDynamicPermissions());
                if (dynamicPermissionSet.contains(module.getAlias())) {
                    modulePojo.setEnable(true);
                }
                // 超级管理员和老板默认有所有paas权限
                if (role.isAdminOrBoss()) {
                    modulePojo.setEnable(true);
                    for (PermissionComplexTermPojo termPojo : modulePerms) {
                        termPojo.setValue(1);
                    }
                } else if (enableModules != null && enableModules.containsKey(id)) {
                    ModulePermissionPojo enableModule = enableModules.get(id);
                    if (enableModule != null) {
                        modulePojo.setEnable(true);
                        PermissionTermsPojo enableModulePerms = enableModule.getPermission();
                        for (PermissionComplexTermPojo termPojo : modulePerms) {
                            if (cloudCodeHelp.isCloudCodeAlias(termPojo.getAlias())) {
                                if (dynamicPermissionSet.contains(termPojo.getAlias())){
                                    termPojo.setValue(1);
                                }
                                continue;
                            }
                            if (ReflectHelper.valueGet(enableModulePerms, termPojo.getAlias()).equals(1)) {
                                termPojo.setValue(1);
                            }
                        }
                    }
                }

                modulePojo.setPermission(modulePerms);
                if (idAndDataPermissionMap.containsKey(id)) {
                    modulePojo.setDataPermission(idAndDataPermissionMap.get(id));
                } else {
                    modulePojo.setDataPermission(role.getDataPermission());
                }
                nowModulePermissions.add(modulePojo);
            }
            // 聚合role的permission
            allModulePermissions = aggregationModulePermissions(allModulePermissions, nowModulePermissions);

        }
        return allModulePermissions;
    }

    /**
     * Description: 聚合saas应用的权限详情
     * @param corpid
     * @param appId
     * @param roleEntityList
     * @return java.util.List<com.xbongbong.paas.pojo.ModulePermissionWithNamePojo>
     * @author 魏荣杰
     * @date 2020/5/12 6:35 下午
     */
    private List<ModulePermissionWithNamePojo> aggregationSaasPermissionDetail(String corpid, Long appId, List<RoleEntity> roleEntityList) throws XbbException {
        List<ModulePermissionWithNamePojo> allModulePermissions = new ArrayList<>();
        // SAAS应用，传输的appId为SAAS应用对应proPermissionId
        Map<String, Object> params = new HashMap<>(16);
        params.put("routerStart", appId);
        params.put("del", 0);
        params.put("orderByStr", "parent_id,sort");
        List<ProPermissionEntity> allModules = proPermissionModel.findEntitys(params);

        List<Integer> saasNoDataPermissionIds = new ArrayList<>();
        // 拆解为两部分，模块权限和模块内权限，构建父子权限
        Map<Integer, ProPermissionEntity> modulePermMap = new LinkedHashMap<>(16);
        for (ProPermissionEntity proPermission : allModules) {
            if (proPermission.getParentId().equals(appId.intValue())) {
                modulePermMap.put(proPermission.getId(), proPermission);
            }
            if (ProPermissionAliasEnum.checkNoDataPermissionByAlias(proPermission.getAlias())) {
                saasNoDataPermissionIds.add(proPermission.getId());
            }
        }
        // 第二次循环，设置childList
        for (ProPermissionEntity proPermission : allModules) {
            if (proPermission.getParentId().equals(appId.intValue())) {
                continue;
            }
            ProPermissionEntity parentPermission = modulePermMap.get(proPermission.getParentId());
            if (parentPermission == null) {
                continue;
            }
            List<ProPermissionEntity> childList = parentPermission.getChildList();
            if (childList == null) {
                childList = new ArrayList<>();
            }
            childList.add(proPermission);
            parentPermission.setChildList(childList);
        }

        // 模块数据权限,拼装数据
        List<PermissionComplexTermPojo> modulePerms;
        // 需要处理未开通搜客或开通搜客试用套餐的公司不允许在管理中心里展示“搜客-权限管理”
        SearchCustomerCompanyEntity soukeEntity = searchCustomerCompanyModel.getByCorpid(corpid, SoukeMealEnum.SOUKE.getType());
        boolean soukeFlag = (soukeEntity == null) || (soukeEntity.getExtraExpiry() - soukeEntity.getAddTime() < 4 * RedisConstant.LONG_DURATION);
        if (soukeFlag) {
            // 移除搜客
            modulePermMap.remove(428);
        }
        if (!dataConnectionService.tplusEnable(corpid)) {
            modulePermMap.remove(987);
        }

        // SaaS应用内PaaS表单处理
        params.clear();
        params.put("aliasIn", ProPermissionAliasEnum.getAppPermissionAlias());
        List<ProPermissionEntity> proPermissionEntityList = proPermissionModel.findEntitys(params);
        ProPermissionAliasEnum proPermissionAliasEnum = null;
        for (ProPermissionEntity entity : proPermissionEntityList) {
            if (Objects.equals(entity.getId(), appId.intValue())) {
                proPermissionAliasEnum = ProPermissionAliasEnum.getByAlias(entity.getAlias());
                break;
            }
        }
        String appAlias = null;
        if (!Objects.isNull(proPermissionAliasEnum)) {
            switch (proPermissionAliasEnum) {
                case CRM:
                    appAlias = SystemAppMenuEnum.CRM.getAlias();
                    break;
                case JXC:
                    appAlias = SystemAppMenuEnum.JXC.getAlias();
                    break;
                case PRODUCT_MANAGEMENT:
                    appAlias = SystemAppMenuEnum.PRODUCT.getAlias();
                    break;
                case FUND_MANAGEMENT:
                    appAlias = SystemAppMenuEnum.FUND_MANAGEMENT.getAlias();
                    break;
                case WORK_ORDER_APP:
                    appAlias = SystemAppMenuEnum.WORK_ORDER.getAlias();
                    break;
                case MARKET_MANAGEMENT:
                    appAlias = SystemAppMenuEnum.MARKET_MANAGEMENT.getAlias();
                    break;
                case CHART_CENTER:
                case PROCESS_APP:
                case MANAGE_CENTER:
                case SMS_APP:
                default:
            }
        }

        Long paasAppId = 0L;
        List<PaasMenuEntity> paasMenuEntityList = new ArrayList<>();
        if (!Objects.isNull(appAlias)) {
            PaasAppEntity paasAppEntity = paasAppModel.getByAlias(appAlias, corpid);
            paasAppId = paasAppEntity.getId();
            params.clear();
            params.put("corpid",corpid);
            params.put("del", 0);
            params.put("appId", paasAppId);
            params.put("typeIn", Arrays.asList(2, 3, 4));
            params.put("orderByStr", "sort");
            params.put("negAliasIn", Collections.singletonList(XbbRefTypeEnum.WORK_REPORT.getAlias()));
            paasMenuEntityList = paasMenuModel.list(params);

            params.clear();
            params.put("corpid",corpid);
            params.put("del", 0);
            params.put("appId", paasAppId);
            params.put("negAliasIn", Collections.singletonList(XbbRefTypeEnum.WORK_REPORT.getAlias()));
            params.put("saasMark", SaasMarkEnum.PAAS.getCode());
            List<PaasFormExplainEntity> paasFormExplainEntityList = paasFormExplainModel.list(params);
            // 删除没有解释的菜单
            Map<Long, PaasFormExplainEntity> menuIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            paasFormExplainEntityList.forEach(item -> menuIdMap.put(item.getMenuId(), item));
            paasMenuEntityList.removeIf(paasMenuEntity -> !menuIdMap.containsKey(paasMenuEntity.getId()));

        }


        for (RoleEntity role : roleEntityList) {
            // 当前的role的permission
            List<ModulePermissionWithNamePojo> nowModulePermissions = new ArrayList<>();
            // 已设置的权限列表
            Set<Integer> permissionIdsSet = role.getPermissionIdsSet();
            // 已设置的数据权限
            String dataPermissionDetailStr = role.getDataPermissionDetail();
            List<DataPermissionDetailPojo> dataPermissionDetailPojos = JSON.parseArray(dataPermissionDetailStr, DataPermissionDetailPojo.class);
            if (dataPermissionDetailPojos == null) {
                dataPermissionDetailPojos = new ArrayList<>();
            }

            List<DataPermissionsPojo> permissions = new ArrayList<>();
            for (DataPermissionDetailPojo pojo : dataPermissionDetailPojos) {
                if (Objects.equals(appId, pojo.getId())) {
                    permissions = pojo.getPermissions();
                }
            }
            Map<Long, Integer> saasDataPermissionMap = new HashMap<>();
            Map<Long, Integer> paasDataPermissionMap = new HashMap<>();
            for (DataPermissionsPojo pojo : permissions) {
                if (Objects.equals(SaasMarkEnum.SAAS.getCode(), pojo.getSaasMark())) {
                    saasDataPermissionMap.put(pojo.getId(), pojo.getDataPermission());
                } else {
                    paasDataPermissionMap.put(pojo.getId(), pojo.getDataPermission());
                }
            }
            for (ProPermissionEntity module : modulePermMap.values()) {
                long id = module.getId().longValue();
                // 初始化默认paas模块权限
                modulePerms = PermissionHelp.initDefaultSaasModulePermission(module);
                cloudCodeHelp.addCloudCodePermission(corpid, module.getAlias(), modulePerms);
                ModulePermissionWithNamePojo modulePojo = new ModulePermissionWithNamePojo();
                modulePojo.setId(id);
                modulePojo.setName(module.getName());
                modulePojo.setType(ModuleTypeEnum.SAAS.getCode());
                modulePojo.setSaasMark(SaasMarkEnum.SAAS.getCode());
                // 默认设为 module的数据库值, PermissionTermsPojo初始化,没有设置数据时传回初始值
                boolean moduleEnable = permissionIdsSet.contains(module.getId());
                modulePojo.setEnable(moduleEnable);

                if (permissionIdsSet != null && permissionIdsSet.size() > 0) {
                    for (PermissionComplexTermPojo termPojo : modulePerms) {
                        if (permissionIdsSet.contains(termPojo.getProPermissionId())) {
                            termPojo.setValue(1);
                            if (!modulePojo.getEnable()) {
                                modulePojo.setEnable(true);
                            }
                        }
                    }
                }

                modulePojo.setPermission(modulePerms);
                if (saasNoDataPermissionIds.contains(module.getId())) {
                    modulePojo.setDataPermission(-1);
                } else {
                    if (saasDataPermissionMap.containsKey(id)) {
                        modulePojo.setDataPermission(saasDataPermissionMap.get(id));
                    } else {
                        modulePojo.setDataPermission(role.getDataPermission());
                    }
                }
                nowModulePermissions.add(modulePojo);
            }

            // SaaS内PaaS表单的处理
            List<AppPermissionPojo> enableAppPermissions = JSON.parseArray(role.getPaasPermissions(), AppPermissionPojo.class);
            AppPermissionPojo thisApp = null;
            if (enableAppPermissions == null) {
                enableAppPermissions = new ArrayList<>();
            }
            for (AppPermissionPojo enableApp : enableAppPermissions) {
                if (Objects.equals(enableApp.getAppId(), paasAppId)) {
                    thisApp = enableApp;
                    break;
                }
            }

            Map<Long, ModulePermissionPojo> enableModules = new HashMap<>();
            if (!Objects.isNull(thisApp) && !Objects.isNull(thisApp.getModules())) {
                for (ModulePermissionPojo enableModule : thisApp.getModules()) {
                    enableModules.put(enableModule.getId(), enableModule);
                }
            }
            List<PermissionComplexTermPojo> modulePaasPerms;
            for (PaasMenuEntity module : paasMenuEntityList) {
                Long id = module.getId();
                modulePaasPerms = PermissionHelp.initDefaultPaasModulePermission();
                cloudCodeHelp.addCloudCodePermission(corpid, module.getAppId(), id, modulePaasPerms);
                ModulePermissionWithNamePojo modulePojo = new ModulePermissionWithNamePojo();
                modulePojo.setId(id);
                modulePojo.setName(module.getName());
                modulePojo.setType(module.getType());
                modulePojo.setSaasMark(SaasMarkEnum.PAAS.getCode());
                // 默认设为 false, PermissionTermsPojo初始化,没有设置数据时传回初始值
                modulePojo.setEnable(false);
                // 超级管理员和老板默认有所有paas权限
                if (role.isAdminOrBoss()) {
                    modulePojo.setEnable(true);
                    for (PermissionComplexTermPojo termPojo : modulePaasPerms) {
                        termPojo.setValue(1);
                    }
                } else if (enableModules.containsKey(id)) {
                    ModulePermissionPojo enableModule = enableModules.get(id);
                    if (enableModule != null) {
                        modulePojo.setEnable(true);
                        PermissionTermsPojo enableModulePerms = enableModule.getPermission();
                        for (PermissionComplexTermPojo termPojo : modulePaasPerms) {
                            if (Objects.equals(ReflectHelper.valueGet(enableModulePerms, termPojo.getAlias()), 1)
                                    || cloudCodeHelp.hasCloudCodePermissions(termPojo.getAlias(), role.getDynamicPermissions())) {
                                termPojo.setValue(1);
                            }
                        }
                    }
                }

                modulePojo.setPermission(modulePaasPerms);
                if (paasDataPermissionMap.containsKey(id)) {
                    modulePojo.setDataPermission(paasDataPermissionMap.get(id));
                } else {
                    modulePojo.setDataPermission(role.getDataPermission());
                }
                nowModulePermissions.add(modulePojo);
            }

            // 聚合role的permission
            allModulePermissions = aggregationModulePermissions(allModulePermissions, nowModulePermissions);
        }
        return allModulePermissions;
    }


    /**
     * Description: 聚合不同role的详情
     * @param allModulePermissions
     * @param nowModulePermissions
     * @return java.util.List<com.xbongbong.paas.pojo.ModulePermissionWithNamePojo>
     * @author 魏荣杰
     * @date 2020/5/12 6:36 下午
     */
    private List<ModulePermissionWithNamePojo> aggregationModulePermissions(List<ModulePermissionWithNamePojo> allModulePermissions, List<ModulePermissionWithNamePojo> nowModulePermissions) {
        if (allModulePermissions.isEmpty()) {
            allModulePermissions = nowModulePermissions;
        } else {

            for (ModulePermissionWithNamePojo pojo : allModulePermissions) {
                Long id = pojo.getId();
                Integer pojoSaasMark = pojo.getSaasMark();

                ModulePermissionWithNamePojo thisModule = null;
                for (ModulePermissionWithNamePojo nowPojo : nowModulePermissions) {
                    if (Objects.equals(id, nowPojo.getId()) && Objects.equals(pojoSaasMark, nowPojo.getSaasMark())) {
                        thisModule = nowPojo;
                        break;
                    }
                }

                if (!Objects.isNull(thisModule)) {
                    if (pojo.getEnable() || thisModule.getEnable()) {
                        pojo.setEnable(true);
                    }
                    if (thisModule.getEnable() && pojo.getDataPermission() < thisModule.getDataPermission()) {
                        pojo.setDataPermission(thisModule.getDataPermission());
                    }
                    List<PermissionComplexTermPojo> permission = pojo.getPermission();
                    List<PermissionComplexTermPojo> nowPermission = thisModule.getPermission();
                    for (PermissionComplexTermPojo complexTermPojo : permission) {
                        for (PermissionComplexTermPojo nowComplexTermPojo : nowPermission) {
                            if (Objects.equals(complexTermPojo.getAlias(), nowComplexTermPojo.getAlias())) {
                                if (Objects.equals(complexTermPojo.getValue(), 1) || Objects.equals(nowComplexTermPojo.getValue(), 1)) {
                                    complexTermPojo.setValue(1);
                                }
                            }
                        }
                    }
                }

            }

        }
        return allModulePermissions;
    }

    @Override
    public RoleAppDetailVO permissionAppDetail(PermissionAppDetailDTO permissionAppDetailDTO) throws XbbException {
        RoleAppDetailVO roleAppDetailVO = new RoleAppDetailVO();

        String corpid = permissionAppDetailDTO.getCorpid();
        String selectUserId = permissionAppDetailDTO.getSelectUserId();

        UserEntity userEntity = userModel.getByKeyIngoreDel(selectUserId, corpid);
        List<Integer> roleIds = userEntity.roleIdsToList();
        List<RoleEntity> roleEntityList = roleModel.getByRoleIdIn(corpid, roleIds);
        // 所有应用权限
        List<AppPermissionWithNamePojo> allAppPermissions = new ArrayList<>();

        // 所有SAAS 应用
        Map<String, Object> params = new HashMap<>(8);
        params.put("parentId", 0);
        params.put("enable", 1);
        params.put("del", 0);
        params.put("orderByStr", "sort");
        List<ProPermissionEntity> allSaasApps = proPermissionModel.findEntitys(params);

        params.clear();
        params.put("corpid", corpid);
        params.put("del", 0);
        params.put("saasMark", 2);
        params.put("orderByStr", "sort");
        // 查询所有 PAAS 应用
        List<PaasAppEntity> allPaasApps = paasAppModel.list(params);

        params.clear();
        params.put("corpid", corpid);
        params.put("aliasIn", ProPermissionAliasEnum.getAppPermissionAlias());
        params.put("del", 0);
        List<ProPermissionEntity> proPermissionEntityList = proPermissionModel.findEntitys(params);
        Map<ProPermissionAliasEnum, Integer> appIdMap = new HashMap<>();
        for (ProPermissionEntity entity : proPermissionEntityList) {
            String alias = entity.getAlias();
            ProPermissionAliasEnum proPermissionAliasEnum = ProPermissionAliasEnum.getByAlias(alias);
            if (Objects.nonNull(proPermissionAliasEnum)) {
                appIdMap.put(proPermissionAliasEnum, entity.getId());
            }
        }

        params.clear();
        params.put("corpid", corpid);
        params.put("aliasIn", SystemAppMenuEnum.getAppAliasList());
        params.put("del", 0);
        List<PaasAppEntity> saasAppList = paasAppModel.findEntitys(params);

        Map<Long, Long> saasIdAndAppIdMap = new HashMap<>();
        for (PaasAppEntity paasAppEntity : saasAppList) {
            String alias = paasAppEntity.getAlias();
            SystemAppMenuEnum systemAppMenuEnum = SystemAppMenuEnum.getSystemAppMenuEnum(alias);
            if (Objects.nonNull(systemAppMenuEnum)) {
                switch (systemAppMenuEnum) {
                    case CRM:
                        saasIdAndAppIdMap.put(appIdMap.get(ProPermissionAliasEnum.CRM).longValue(), paasAppEntity.getId());
                        break;
                    case PRODUCT:
                        saasIdAndAppIdMap.put(appIdMap.get(ProPermissionAliasEnum.PRODUCT_MANAGEMENT).longValue(), paasAppEntity.getId());
                        break;
                    case JXC:
                        saasIdAndAppIdMap.put(appIdMap.get(ProPermissionAliasEnum.JXC).longValue(), paasAppEntity.getId());
                        break;
                    case FUND_MANAGEMENT:
                        saasIdAndAppIdMap.put(appIdMap.get(ProPermissionAliasEnum.FUND_MANAGEMENT).longValue(), paasAppEntity.getId());
                        break;
                    case MARKET_MANAGEMENT:
                        saasIdAndAppIdMap.put(appIdMap.get(ProPermissionAliasEnum.MARKET_MANAGEMENT).longValue(), paasAppEntity.getId());
                        break;
                    case WORK_ORDER:
                        break;
                    case CALL_CENTER:
                        break;
                    case CALL_CENTER_DU_YAN:
                        break;
                    case GROUP_MESSAGE:
                        break;
                    case SEARCH_CUSTOMER:
                        break;
                    default:
                }
            }
        }

        for (RoleEntity role : roleEntityList) {
            List<AppPermissionWithNamePojo> nowAppPermissions = new ArrayList<>();
            // saas已设置权限
            Set<Integer> permissionIdsSet = role.getPermissionIdsSet();
            for (ProPermissionEntity saasApp: allSaasApps) {
                AppPermissionWithNamePojo appPojo = new AppPermissionWithNamePojo();
                appPojo.setAppId(saasApp.getId().longValue());
                appPojo.setName(saasApp.getName());
                appPojo.setSaasMark(SaasMarkEnum.SAAS.getCode());
                if (role.isAdminOrBoss() || permissionIdsSet.contains(saasApp.getId())) {
                    appPojo.setEnable(true);
                } else {
                    appPojo.setEnable(false);
                }
                nowAppPermissions.add(appPojo);
            }


            // 解析appPermissionWithNamePojo，传入应用名和表单/报表名
            List<AppPermissionWithNamePojo> enableAppPermissions = JSON.parseArray(role.getPaasPermissions(), AppPermissionWithNamePojo.class);
            if (enableAppPermissions == null) {
                // 兼容数据库中为空的情况
                enableAppPermissions = new ArrayList<>();
            }
            // 转化为有权限的appId Set
            Set<Long> enableAppIds = new HashSet<>();
            for (AppPermissionWithNamePojo enableApp : enableAppPermissions) {
                enableAppIds.add(enableApp.getAppId());
            }

            for (PaasAppEntity app : allPaasApps) {
                AppPermissionWithNamePojo appPojo = new AppPermissionWithNamePojo();
                appPojo.setAppId(app.getId());
                appPojo.setName(app.getName());
                appPojo.setSaasMark(app.getSaasMark());
                if (role.isAdminOrBoss() || enableAppIds.contains(app.getId())) {
                    appPojo.setEnable(true);
                } else {
                    appPojo.setEnable(false);
                }
                nowAppPermissions.add(appPojo);
            }

            for (AppPermissionWithNamePojo pojo : nowAppPermissions) {
                Long appId = pojo.getAppId();
                Long paasAppId = saasIdAndAppIdMap.get(appId);
                if (enableAppIds.contains(paasAppId)) {
                    pojo.setEnable(true);
                }
            }

            // 聚合权限
            if (allAppPermissions.isEmpty()) {
                allAppPermissions = nowAppPermissions;
            } else {
                for (AppPermissionWithNamePojo pojo : allAppPermissions) {
                    for (AppPermissionWithNamePojo nowPojo : nowAppPermissions) {
                        if (Objects.equals(pojo.getAppId(), nowPojo.getAppId()) && Objects.equals(pojo.getSaasMark(), nowPojo.getSaasMark())) {
                            if (pojo.getEnable() || nowPojo.getEnable()) {
                                pojo.setEnable(true);
                            }
                            break;
                        }
                    }
                }
            }
        }


        roleAppDetailVO.setAppPermissions(allAppPermissions);
        return roleAppDetailVO;
    }

    @Override
    public BaseVO userInfoAuth(UserInfoAuthDTO userInfoAuthDTO) throws XbbException {

        String corpid = userInfoAuthDTO.getCorpid();
        UserEntity userEntity = userModel.getByKey(userInfoAuthDTO.getUserId(), corpid);
        if (Objects.isNull(userEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100004);
        }

        // 临时授权码换取accessToken
        String accessTokenUrl = Env.API_HOST + "/v1.0/oauth2/userAccessToken";
        JSONObject args = new JSONObject();
        args.put("clientId", Env.SUITE_KEY);
        args.put("clientSecret", Env.SUITE_SECRET);
        args.put("code", userInfoAuthDTO.getAuthCode());
        args.put("grantType", "authorization_code");

        String accessToken;
        JSONObject tokenResponse;
        try {
            tokenResponse = restTemplateHelper.post(accessTokenUrl, args);
        } catch (RestClientException e) {
            LOG.error("/v1.0/oauth2/userAccessToken接口获取钉钉用户token失败！", e);
            tokenResponse = null;
        }
        if (Objects.nonNull(tokenResponse) && tokenResponse.containsKey("accessToken")) {
            accessToken = tokenResponse.getString("accessToken");
        } else {
            // todo 从钉钉接口获取信息失败
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100024);
        }

        // 获取用户通讯录个人信息（/v1.0/contact/users/{unionId}），如需获取当前授权人的信息，unionId参数可以传me
        String contactUrl = Env.API_HOST + "/v1.0/contact/users/me";
        JSONObject headers = new JSONObject();
        headers.put("Content-Type", "application/json");
        headers.put("x-acs-dingtalk-access-token", accessToken);

        JSONObject contactUserInfo;
        try {
            contactUserInfo = restTemplateHelper.get(contactUrl, headers);
        } catch (XbbException e) {
            LOG.error("/v1.0/contact/users/me接口获取钉钉用户个人信息失败！", e);
            contactUserInfo = null;
        }

        if (Objects.isNull(contactUserInfo)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100024);
        }

        // 保存个人信息
        String mobile = contactUserInfo.containsKey("mobile") ? contactUserInfo.getString("mobile") : "";
        String email = contactUserInfo.containsKey("email") ? contactUserInfo.getString("email") : "";
        userEntity.setMobile(mobile);
        userEntity.setEmail(email);
        try {
            userModel.update(userEntity);
        } catch (XbbException e) {
            LOG.error("更新员工信息失败！", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, ErrorMessageConstant.SAVE_ERROR);
        }

        // 钉钉管理员或主管调用admin平台方法同步联系人到逍邦公司
        boolean isAdminOrLeader = userEntity.isOriAdmin() || userEntity.isLeader();
        if (isAdminOrLeader) {

            args.clear();
            // 设置参数
            Set<DepartmentVO> depSet = userInfoAuthDTO.getLoginUser().getDepSet();
            Set<RoleSimpleVO> roleSet = userInfoAuthDTO.getLoginUser().getRoleSet();
            StringBuilder depNameBuffer = new StringBuilder();
            StringBuilder roleNameBuffer = new StringBuilder();

            // 部门
            for (DepartmentVO departmentVO : depSet) {
                depNameBuffer.append(departmentVO.getName()).append(StringConstant.COMMA);
            }
            String departmentConcatStr = depNameBuffer.toString();
            if (departmentConcatStr.length() > 0) {
                departmentConcatStr = departmentConcatStr.substring(0, departmentConcatStr.length() - 1);
            }
            // 角色
            for (RoleSimpleVO roleSimpleVO : roleSet) {
                roleNameBuffer.append(roleSimpleVO.getRoleName()).append(StringConstant.COMMA);
            }
            String roleConcatStr = roleNameBuffer.toString();
            if (roleConcatStr.length() > 0) {
                roleConcatStr = roleConcatStr.substring(0, roleConcatStr.length() - 1);
            }

            // 改为脚本服务缓存添加的联系人
            SyncUserToContactPojo syncUserToContactPojo = new SyncUserToContactPojo(corpid, userEntity.getUserId(), userEntity.getName(), mobile, departmentConcatStr, roleConcatStr);

            SyncUserToContactDTO syncUserToContactDTO = new SyncUserToContactDTO();
            syncUserToContactDTO.setKey(BasicConstant.TASK_SECRET_KEY);
            syncUserToContactDTO.setCorpid(corpid);
            syncUserToContactDTO.setUserId(userEntity.getUserId());
            syncUserToContactDTO.setPlatform(PlatFormEnum.INTERNAL.getValue());
            syncUserToContactDTO.setUser(syncUserToContactPojo);

            Locale locale = LocaleContextHolder.getLocale();
            String lang = locale.toString();

            XbbResponse<ChartCategoryInitVO> xbbContactRedisResp = syncDataToXbbFeignClient.addContactRedis(syncUserToContactDTO, lang);

            if (!xbbContactRedisResp.isSuccess()) {
                LOG.error("缓存员工到script脚本服务失败！", xbbContactRedisResp.getMsg());
            }
        }

        return new BaseVO();
    }


    @Override
    public BaseVO addMembers(UserMembersAddDTO userMembersAddDTO){
        String corpid = userMembersAddDTO.getCorpid();
        String userId = userMembersAddDTO.getUserId();
        long now = DateTimeUtil.getInt();
        //插入新添加的常用成员
        teamRedisHelper.addRecentlyMember(corpid,userId,userMembersAddDTO.getMembersAddList(),now);
        //删除多余的成员
        teamRedisHelper.removeExtraMembers(corpid,userId);
        return new BaseVO();
    }

    @Override
    public UserMembersVO getMembers(UserMembersGetDTO userMembersGetDTO) throws XbbException{
        UserMembersVO userMembersVO  = new UserMembersVO();
        String corpid = userMembersGetDTO.getCorpid();
        String userid = userMembersGetDTO.getUserId();
        Long formId = userMembersGetDTO.getFormId();
        String attr = userMembersGetDTO.getAttr();
        Long dataId = userMembersGetDTO.getDataId();
        Integer saasMark = userMembersGetDTO.getSaasMark();
        Integer businessType = userMembersGetDTO.getBusinessType();
        Set<String> recentlyMembers = teamRedisHelper.getRecentlyMembers(corpid, userid);
        List<String> userIdList = new ArrayList<>(recentlyMembers);
        //List<UserEntity> memberList = userModel.findEntitysByUserIds(userIdList, corpid);
        //过滤用户列表数据可选范围
        Map<String, Object> param = new HashMap<>();
        param.put(ParameterConstant.CORPID,corpid);
        param.put(ParameterConstant.USER_ID_IN,userIdList);
        Map<String, Object> userOptionalRange = new HashMap<>();
        if (Objects.nonNull(formId) && StringUtils.isNotEmpty(attr) && formId != 0L){
            PaasFormExplainEntity paasFormExplainEntity = proFormHelp.getExplainEntity(corpid, formId, businessType);
            if (Objects.nonNull(paasFormExplainEntity)) {
                Map<String, FieldAttrEntity> thisExplainMap = ExplainUtil.getAllSubFormExplainMap(paasFormExplainEntity.getExplains());
                FieldAttrEntity fieldAttrEntity = thisExplainMap.get(attr);
                if (Objects.nonNull(fieldAttrEntity)){
                    LimitChooseRangePoJo limitChooseRange = fieldAttrEntity.getLimitChooseRange();
                    if (Objects.nonNull(limitChooseRange) && Objects.equals(limitChooseRange.getType(), LimitChooseRangeTypeEnum.CUSTOM.getType())){
                        //开启自定义范围筛选标记
                        userMembersVO.setOpenRangeFilter(1);
                        UserListDTO userListDTO = new UserListDTO();
                        userListDTO.setCorpid(corpid);
                        userListDTO.setDataId(dataId);
                        userListDTO.setBusinessType(businessType);
                        userListDTO.setSaasMark(saasMark);
                        userListDTO.setLoginUser(userMembersGetDTO.getLoginUser());
                        userListDTO.setOptionalRangeDataList(userMembersGetDTO.getOptionalRangeDataList());
                        userOptionalRange = filterUserList(userListDTO, limitChooseRange);
                        if (Objects.isNull(userOptionalRange)) {
                            userMembersVO.setOpenRangeFilter(0);
                        }else{
                            param.put("userOptionalRange", userOptionalRange);
                        }
                    }
                }
            }
        }

        param.put("userOptionalRange", userOptionalRange);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        List<UserEntity> memberList = userModel.findEntitys(param);
        //查询出来之后顺序默认按照id排序了，需要重新排序，最后添加的成员放在最上面
        Map<String, UserEntity> memberMap = memberList.stream().collect(Collectors.toMap(UserEntity::getUserId, v -> v));
        List<UserEntity> sortList = new ArrayList<>();
        for (String userId : userIdList) {
            sortList.add(memberMap.get(userId));
        }
        sortList = sortList.stream().filter(v -> !Objects.isNull(v)).collect(Collectors.toList());
        List<UserVO> memberUserVoList = new ArrayList<>();
        try {
            BeanUtil.copyPropertiesList(sortList, memberUserVoList, UserVO.class);
        } catch (InstantiationException | IllegalAccessException e) {
            LOG.error("UserService.getMembers 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        userMembersVO.setMemberList(memberUserVoList);
        return userMembersVO;
    }


}
